Java类加载与初始化

原创 2016年05月31日 15:42:35


一、类的生命周期

1虚拟机的加载机制

  Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制。

类从被加载到虚拟机内存中开始,直到卸载出内存为止,它的整个生命周期包括

 

 

加载(即生成Class对象)->链接(验证+准备+解析)(即相当于jvm编译,会给类静态变量默认值)->初始化(使用前的准备,也是部分初始化JAVA代码开始,如构造函数,和类静态变量的初始值)->使用->卸载

其中验证、准备、解析统称为连接。加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类的加载过程必须按照这个顺序来按部就班地开始,而解析阶段则不一定,它在某些情况下可以在初始化阶段后再开始。

(2)类的加载时机

虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握。

(3)类的初始化时机

在类初始化之前要完成类的加载和连接。类初始化的时机,首次主动使用该类时会触发初始化,

1、遇到new、getstatic、putstatic、invokestatic这四条字节码指令的时候。

     a .用new实例化一个类时

  b.读取或者设置类的静态字段时(不包括被final修饰的静态字段,因为他们已经被塞进常量池了)

  特殊情况:public static final int A = 4 + new Random().nextInt(10);//静态final   变量在编译时不定的情况

  c.以及执行静态方法的时候。

2、使用java.lang.reflect进行反射调用的时候。

3、当初始化一个类的时候,发现其父类还没有初始化,那么先去初始化它的父类。

4、当虚拟机启动的时候,需要初始化main函数所在的类。

以上情况称为称对一个类进行 “主动引用” ,除此种情况之外,均不会触发类的初始化,称为 “被动引用”

接口的加载过程与类的加载过程稍有不同。接口中不能使用static{}块。当一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有真正在使用到父接口时(例如引用接口中定义的常量)才会初始化。

二、对类的“被动引用”(类不会被初始化)

1通过子类引用父类的静态字段,父类会初始化,不会导致子类的初始化


class SuperClass{
    static{
        System.out.println("父类初始化");
    }
    public static int value=100;
}
 
class SubClass extends SuperClass{
    static{
        System.out.println("子类初始化.");
    }
}
 
public class Test1{
    public static void main(String[]args){
        System.out.println(SubClass.value);
    }
    
}

输出结果为:

父类初始化

100

2通过数组引用来引用类,不会触发此类的初始化

class SuperClass{
    static{
        System.out.println("父类初始化");
    }
    public static int value=100;
}
 
public class Test1{
    public static void main(String[]args){
         SuperClass[] s = new SuperClass[5];
    }
    
}

无结果输出,就是不会对SuperClass进行初始化

(3)常量在编译阶段会被存入调用类的常量池中,本质上并没有引用到定义常量类,所以自然不会触发定义常量的类的初始化

class ConstClass
{
    static{
        System.out.println("ConstClass init.");
           }
public final static Stringvalue="hello world";
 }
 
public class Test1
{
    public static void main(String[]args){
     System.out.println(ConstClass.value);
}


输出结果:hello world

只调用ConstClass类中的常量 不会初始化ConstClass类。

三、类在JVM中的工作原理

(1)类的加载

从字节码二进制文件——.class文件将类加载到内存,从而达到类从硬盘上到内存上的一个迁移,所有的程序必须加载到内存才能工作。

将内存中的class放到运行时数据区的方法区内,之后在堆区建立一个java.lang.Class对象,用来封装方法区的数据结构。类加载的最终产物就是堆中的一个java.lang.Class对象。

(2)连接

    1)验证:出于安全性的考虑,验证内存中的字节码是否符合JVM的规范,类的结构规范、语义检查、字节码操作是否合法、这个是为了防止用户自己建立一个非法的XX.class文件就进行工作了,或者是JVM版本冲突的问题,比如在JDK1.7下面编译通过的class(其中包含注解特性的类),是不能在JDK1.4的JVM下运行的。

 

 2)准备:将类的静态变量进行分配内存空间、初始化默认值。注意是初始值。

默认的初始值类型如下:

整数类型(byte、int、short、long):0

浮点类型(float、double):0.0

字符类型(char):(‘\u0000

布尔类型(boolean):false

引用类型(类、接口、数组):null

3)解析:把类的符号引用转为直接引用

(3)类的初始化

版权声明:转载请标明出处

相关文章推荐

java 类加载调试

  • 2014年12月22日 21:55
  • 1.01MB
  • 下载

Java 类加载与初始化

类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用。 每个类编译后产生一个Class对象,存储在.class文件中,...
  • CHBSRZF
  • CHBSRZF
  • 2015年09月16日 15:02
  • 331

Java类加载内幕

  • 2007年12月20日 17:54
  • 1.04MB
  • 下载

Java类加载说明

  • 2008年01月19日 14:21
  • 239KB
  • 下载

Java杂谈3——类加载机制与初始化顺序

Java语言的哲学:一切都是对象。对于Java虚拟机而言,一个普通的Java类同样是一个对象,那如果是对象,必然有它的初始化过程。一个类在JVM中被实例化成一个对象,需要经历三个过程:加载、链接和初始...

Java类加载原理解析.rar

  • 2009年10月10日 16:22
  • 105KB
  • 下载

Java学习总结6——类加载1(类初始化顺序)

出处:http://www.cnblogs.com/jackyrong/archive/2008/08/12/1266161.html 我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构...

Java 类加载与初始化

在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用。 每个类编译后产生一个Class对象,存储在.class文件中,...

Java类加载和初始化相关知识

《深入理解Java虚拟机++JVM高级特性与最佳实践》类的初始化类从被加载到虚拟机内存中开始,到卸载出内存开始,它的生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载七个阶段,其中验证、准备和...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java类加载与初始化
举报原因:
原因补充:

(最多只允许输入30个字)