JVM加载类的时机
2018-07-26 本文已影响16人
四喜汤圆
image.png
摘自 深入理解java虚拟机【Java虚拟机类生命周期】
类的生命周期
加载,连接(验证,准备,解析),初始化,使用,卸载
摘自 深入理解java虚拟机【Java虚拟机类生命周期】
对类的主动引用(5种),会触发类的初始化
Java虚拟机规范中对于类加载的时机没有明确的规范,但是明确规定了有且只有5种情况下,必须立即对类进行初始化。(既然执行了初始化,加载、连接操作肯定在初始化之前已经开始(并不保证结束的顺序))
- 读取或设置类的静态变量、访问类的静态方法时,若该类还未被初始化,则需先进行初始化
- 创建类的实例时,若该类还未被初始化,则需先进行初始化
- 通过new关键字创建
- 通过反射方法(java.lang.reflect)创建
- 当要初始化一个类时,若其父类还未初始化,则先初始化其父类
- JVM启动时,会先初始化包含main()方法的类
- 当使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个句柄所对应的类没有进行过初始化,则需先触发其初始化。
上述5种情况称为对类的主动引用,下面介绍几种对类的被动引用情况
对类的被动引用(列举3个),不会触发类的初始化
- 通过子类引用父类的静态变量,不会触发子类的初始化
// 父类
public class SuperClass{
public static int a=1;
}
// 子类
public class SubClass extends SuperClass{
public static void main(String[] args){
System.out.println(SubClass.a)
}
}
- 通过数组定义引用类,不会触发该类的初始化
public class Main{
public static void main(String[] args){
SuperClass[] arr=new SuperClass[10];
}
}
- 通过类名访问该类中的常量,不会触发该类的初始化
public class ConstClass{
public static final String HELLO_WORLD="hello";
}
public class Main{
public static void main(String[] args){
ConstClass.HELLO_WORLD;
}
}