JVM类加载分为5个过程:加载,验证,准备,解析,初始化,使用,卸载,如下图所示:
加载是指 查找字节流 并据此 创建类 的过程。
BootStrap ClassLoader
、 ClassLoader
、 ExtClassLoader
、 AppClassloader
等类加载器来查找字节流并创建的。 连接是指将创建好的类放入JVM并使之能够很好的执行的过程。
它可分为验证、准备、解析三个步骤。
初始化的目的是为标记为常量的字段赋值,以及执行 clinit
方法的过程。
在初始化一个静态字段的时候,我们可以再声明时直接赋值,也可以在静态代码块中对其进行赋值。
如果直接赋值的字段被final所修饰,并且字段为基本数据类型和String类型,那么该字段会被编译标记为常量值,其初始化直接由JVM完成。除此之外的所有直接赋值和静态代码块中赋值操作,会被java编译器放到 clinit
方法中。
(1) 虚拟机启动的时候,初始化用户指定的主类。
(2) 使用new该类实例化对象的时候。
(3) 访问静态字段或静态方法时,初始化静态字段或静态方法所在类。
(4) 子类初始化会触发父类初始化。
(5) 如果接口定义了default方法,那么实现该接口的类初始化会触发该接口的初始化。
(6) 使用反射API的时候。
(7) 当使用JDK1.7的动态语言支持时,如果一个java.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。
参考链接:
nomico271.github.io/2017/07/07/…