Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。Java天生可以动态扩展的语言特性就是依赖运行期间动态加载和动态链接这个特点实现的。
1. 类加载的时机
一个类型从被加载到虚拟机内存中开始,到卸载为止,它的整个生命周期将会经过 加载、验证、准备、解析、初始化、使用、卸载七个阶段。其中 验证、准备、解析三个部分统称为 连接
加载、验证、准备、初始化和卸载这五个步骤是不变的,但是解析却不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行是的绑定特性(动态绑定或者晚期绑定)。解析时间具体由虚拟机自己掌握
《Java虚拟机规范》严格规定有且只有六种情况必需对类进行初始化。
-
遇到new、getstatic、 putstatic或invokestatic这 四条字节码指令时,如果类型没有进行过初始化,则需要先触发其初始化阶段。能够生成这四条指令的典型Java代码场景有:
-
使用new关键字实例化对象的时候。
-
读取或设置一个类型的静态字段(被fnal修饰、已在编译期把结果放入常量池的静态字段除外)的时候。
-
调用一个类型的静态方法的时候。
-
-
使用java. langeflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需要先触发其初始化。
-
当初始化类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
-
当虚拟机启动时,用户需要指定一个要执行的主类( 包含main)方法的那个类),虚拟机会先初始化这个主类。
-
当使用JDK 7新加入的动态语言支持时,如果- - -个java. lang invoke. MethodHandle实例最后的解析结果为REF_ getStatic、 REF_ putStatic、 REF_ invokeStatic、 REF newInvokeSpecial四种 类型的方法句柄,并且这个方法句柄对应的类没有进行过初始化,则需要先触发其初始化。
-
当一个接口中定义了JDK 8新加入的默认方法(被default关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,那该接口要在其之前被初始化。
简化:1.使用new关键字,调用类中的静态属性,调用类中到的静态方法 2.反射调用一个类 3.子类进行初始化 4.类为启动类 5.类的初始化导致实现的接口初始化 6.动态语言