JVM-类加载时机

1、类的生命周期

类的生命周期有这七个阶段,加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载,具体如下图所示:

JVM-类加载时机_第1张图片

 

其中加载、验证、准备、初始化和卸载顺序是确定的,类加载必须按照这个顺序开始,但解析阶段可能存在在初始化之后才开始,如Java语言的运行时绑定。
需要注意的是,这几个阶段有可能是交替进行的,并不是一一按顺序来执行,等待一个阶段结束,另外一个阶段才开始。
2、什么时候开始
当真正使用主动引用到类的时候,才会触发类加载

 2.1、主动引用

  • 遇到 new、getstatic、putstatic、invokestatic 字节码指令,例如:
    • 使用 new 实例化对象;
    • 读取或设置一个类的 static 字段(被 final 修饰的除外);
    • 调用类的静态方法。
  • 对类进行反射调用;
  • 初始化一个类时,其父类还没初始化(需先初始化父类);
    • 这点类与接口具有不同的表现,接口初始化时,不要求其父接口完成初始化,只有真正使用父接口时才初始化,如引用父接口中定义的常量。
  • 虚拟机启动,先初始化包含 main() 函数的主类;
  • JDK 1.7 动态语言支持:一个 java.lang.invoke.MethodHandle 的解析结果为 REF_getStatic、REF_putStatic、REF_invokeStatic。

2.2、被动引用

  • 通过子类引用父类静态字段,不会导致子类初始化;
  • Array[] arr = new Array[10]; 不会触发 Array 类初始化;
  • static final VAR 在编译阶段会存入调用类的常量池,通过 ClassName.VAR 引用不会触发 ClassName 初始化。

2.3、接口的加载

与类加载过程有点不一样,它的初始化需要在父接口全部完成初始化,同时真正使用到了父接口的时候才会进行初始化(初始化自然包含前边的几个阶段了)

 

你可能感兴趣的:(JVM,java)