JVM中java类的载入时机

Java虚拟机把描写叙述类的数据从Class文件载入到内存。并对数据进行校验、转换解析和初始化。终于形成能够被虚拟机直接使用的Java类型。这就是虚拟机的载入机制。
类从被载入到虚拟机内存中開始,到卸载出内存为止。它的整个生命周期包含了:载入(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(using)、和卸载(Unloading)七个阶段。

当中验证、准备和解析三个部分统称为连接(Linking),例如以下如所看到的。


这七个阶段,载入、验证、准备、初始化和卸载这五个阶段的顺序是确定的。类的载入过程必须依照这个顺序来按部就班地開始,而解析阶段则不一定,它在某些情况下能够在初始化阶段后再開始。

类的生命周期的每个阶段通常都是互相交叉混合式进行的。一般会在一个阶段运行的过程中调用或激活另外一个阶段。


Java虚拟机规范没有强制性约束在什么时候開始类载入过程。可是对于初始化阶段,虚拟机规范则严格规定了有且仅仅有四种情况必需马上对类进行“初始化”(而载入、验证、准备阶段则必需在此之前開始)。这四种情况归类例如以下:

1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时。假设类没有进行过初始化,则须要先触发其初始化。生成这4条指令最常见的Java代码场景是:使用newkeyword实例化对象时、读取或者设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)时、以及调用一个类的静态方法的时候。
2.使用java.lang.reflect包的方法对类进行反射调用的时候。假设类没有进行过初始化,则须要先触发其初始化。
3.当初始化一个类的时候,假设发现其父类还没有进行过初始化,则须要触发父类的初始化。


4.当虚拟机启动时,用户须要指定一个运行的主类(包括main()方法的类),虚拟机会先初始化这个类。
对于这四种触发类进行初始化的场景,在java虚拟机规范中限定了“有且仅仅有”这四种场景会触发。这四种场景的行为称为对类的主动引用,除此以外的全部引用类的方式都不会触发类的初始化,称为被动引用。

以下通过三个实例来说明被动引用:

演示样例1:

父类SuperClass.java 
public class SuperClass {  
    static{  
         System.out.println("SuperClass init!");  
      }  
     public static int value = 123;  
}  
子类SubClass.java
     public class SubClass extends SuperClass {  
     static{  
        System.out.println("SubClass init!");  
    }  
}  
 
主类NotInitialization.java
public class NotInitialization {  
    public static void main(String[] args) {  
        System.out.println(SubClass.value);  
    }  
}  
输出结果:

SuperClass init! 

123  


由结果能够看出仅仅输出了“SuperClass init!

”,没有输出“SubClass init。”。这是由于对于静态字段,仅仅有直接定义该字段的类才会被初始化。因此当我们通过子类来引用父类中定义的静态字段时,仅仅会触发父类的初始化,而不会触发子类的初始化。

演示样例2:

SuperClass[ ]   scs=new SuperClass[11];


如上。当初始化一个对象数组的时候。也不会触发类的初始化。

演示样例3:

public class ConstClass {

   static {

    system.out.printl("const");

}

   public static final int age =123;  

}

public class NotInitialization{

     public static void main(String[ ] args){

     system.out.println(ConstClass.age);

}

此时并不会出现 “const”,由于在NotInitialization类在编译的时候已经把ConstClass中的变量age放在常量池中了,訪问时直接取出age就可以。不会引发ConstClass的初始化。

 

 

posted on 2017-05-30 12:06  yjbjingcha  阅读(174)  评论(0编辑  收藏  举报

导航