虚拟机规范中严格规定有且只有5种情况下,当类没有初始化时必须立即对类进行初始化:
-
- 遇到new、getstatic、putstatic或invokeStatic这4条字节码指令时。常见场景:
- 使用new关键字实例化对象时,触发new;
- 读取类变量时,触发getstatic;(final常量除外)
- 设置类变量时,触发putstatic;
- 调用类的静态方法时,触发invokeStatic;
- 虚拟机启动时,需指定一个要执行的主类(含有main()的类),虚拟机会先初始化该类;
- 初始化一个类时,当其父类没有初始化,则需要先触发其父类的初始化;
- 使用java.lang.reflect包中的方法对类进行反射调用时;
- 当java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且该句柄所对应的类没有进行过初始化;
你所不知道的MethodHandle
- 当java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且该句柄所对应的类没有进行过初始化;
上面讲到final常量不能触发类初始化,是由于在编译时已把数据放入常量池的静态字段,当读取类的static final字段时,并不需要初始化类,而是从常量池中去获取相应的数据。
上述的5种场景的行为都是对类的一个主动引用过程。除此之外,还有被动引用并不会除非类的初始化过程。
网友评论