2013-03-15 08:56:08.0|分类: jvm|浏览量: 1847
|
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制。 虚拟机规范规定了有且仅有四种情况必须立即对类进行初始化: (1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。 (2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发初始化。 (3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。 (4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类 上面的情况称为对一个类进行主动引用。除此之外所有引用类的方式,都不会触发初始化,称为被动引用。 被动引用情形一: package com.java.initialization;
public class SuperClass {
static {
System.out.println("SuperClass init");
}
public static int value = 123;
}
package com.java.initialization;
public class SubClass extends SuperClass {
static {
System.out.println("SubClass init");
}
}
package com.java.initialization;
public class NotInitialization {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(SubClass.value);
}
}
结果:
SuperClass init 123 这个很奇怪吧!只输出了SuperClass init ,对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。 被动引用情景二 package com.java.initialization;
public class ConstClass {
static {
System.out.println("ConstClass inti ");
}
public static final String name = "name";
}
package com.java.initialization;
public class NotInitialization {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(ConstClass.name);
}
}
结果:
name 这有很奇怪了!没有输出“ConstClass inti ”,这是因为constClass类中的常量name,在编译阶段将此常量的值存储到了NotInitialization类的常量池中,实际上NotInitialization的class文件之中没有constClass类的符号引用入口,者各类在编译成class之后就不存在任何联系了。 注:当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化,并不要求其父类接口全部都完成了初始化,只有在真正使用到父接口的时候才会初始化。 通过数组定义类应用类:ClassA [] array=new ClassA[10]。触发了一个名为[LClassA的类的初始化,它是一个由虚拟机自动生成的、直接继承于Object的类,创建动作由字节码指令newarray触发。 参考《深入理解java虚拟机》 |
