关于类加载的时机问题
一个类型从被加载到jvm内存中开始,再到卸载出内存为止,其经历加载、验证、准备、解析、初始化、使用、卸载七个阶段,通常称验证、准备、解析为链接;
加载、验证、准备、初始化、卸载这五个的顺序是确定的,但是解析阶段可以放到初始化的之后。
对于初始化阶段,《Java虚拟机规范》中规定有且只有以下六种情况必须立即对类进行初始化:
1、当遇到new、getstatic、putstatic、invokestatic这四条字节码指令时,若是没有进行过初始化,则会先进行初始化;
1)使用new关键字实列化对象时;
2)读取或者设置一个类型的静态字段时;
3)调用一个类型的静态方法时;
2、使用java.lang.reflect包的方法对类型进行反射调用时;
3、当初始化类时,若是其对应的父类没有进行过初始化,则其父类需要先进行初始化;
4、当jvm启动时,用户需要指定一个执行的主类,jvm会首先初始化这个主类;
5、当一个接口中使用了默认方法,若是这个接口的实现类发生了初始化,那么这个接口需要在对应的实现类之前初始化(java8中被default关键字修饰的接口方法);
6、当使用java7的动态语言支持时,若是java.long.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄时,且这个方法句柄没有进行过初始化;
以上六种情况属于主动引用。
如下为被动引用:
package com.jia;
public class Test05 {
public static int value = 1;
static{
System.out.println("superClass");
}
}
package com.jia;
public class Test06 extends Test05{
public static int value1 = 2;
static{
System.out.println("subClass");
}
}
package com.jia;
public class Test04 {
public static void main(String[] args) {
System.out.println(Test05.value);
}
}
执行结果:
superClass
1
Process finished with exit code 0