类的生命周期
一个类的生命周期为:加载–>连接–>初始化–>使用–>卸载。其中连接包括验证–>准备–>解析。
初始化时机
在Java虚拟机规范中,对于类加载中的第一阶段“加载”并没有明确的规定,但是对于“初始化”阶段什么时候开始则做出了非常严格的规定,指出有且只有6中场景会触发初始化。
1、遇到new,getStatic,putStatic,invokeStatic这四条字节码指令时:
- 使用new创建一个实例对象
- 读取或设置一个类型的静态字段(被final修饰、已在编译期把结果放入常量池真的静态字段除外)的时候
- 调用一个类型的静态方法的时候
2、使用反射调用方法时,如果类型没有被初始化,那么首先要进行初始化。
3、当初始化类时,如果其父类没有被初始化,则会先触发其父类的初始化
4、当虚拟机启动时,用户首先需要制定一个main方法作为启动类,虚拟机会先初始化这个主类。
5、JDK7新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例的解析结果为REF_getStatic,REF_putStatic,REF_invokeStatic,REF_newInvokeSpecial这四种类型的方法句柄,并且这个方法句柄没有被初始化时,则需先触发其初始化。
6、JDK8中,一个接口定义了默认方法(被default修饰的接口方法),如果有这个接口的实现类发生了初始化,那么该接口要先在该实现类初始化之前初始化。
这六种场景中的行为称为对一个类型进行主动引用。除此之外,所有引用类型的方式都不会触发初始化操作,称为被动引用。
参考文献:《深入理解Java虚拟机》第七章
|