前言
java虚拟机会将Class文件加载到内存当中,并对加载的数据进行校验、转换解析和初始化,最终形成java类型,这就是虚拟机的类加载机制。
java的类加载都是在程序运行期间完成的,包括加载、连接、初始化等等。
类加载生命周期
类从被加载到内存开始,到卸载到内存为止,整个声明周期包括:
加载 —> 验证 —> 准备 —> 解析 —> 初始化 —> 使用 —> 卸载
一般这些顺序是固定的,但是解析不一定。
**
加载
加载是类加载(Class Loading)过程的一个阶段。主要包括:
通过类全限定名称获取定义类的二进制字节流;
注:获取不限,可以从ZIP包、网络、动态生成、文件等等。
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
- 在内存中生成代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口。
验证
目的:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,不会危害虚拟机自身的安全。
- 文件格式验证:当前虚拟机能否处理,包括字节流是否魔数开头,版本能否解析等;
- 元数据验证:当前Class是否符合Java语言要求,包括是否有父类,是否被final修饰等等;
- 字节码验证:确定程序语义是否合法、符合逻辑;
- 符号引用验证:将符号引用转化为直接引用。
准备
目的:正式为类变量分配内存并设置类变量初始值
解析
目的:将常量池内的符号引用替换为直接引用。
初始化
对于初始化阶段,虚拟机规定遇到有且只有这5种情况时,必须进行类的初始化操作(加载、验证、准备、解析是必须的):
- 遇到new、getstatic、putsatic、invkestatic指令时触发初始化。
- 使用java.lang.reflect包的方法对类进行反射调用的时候,触发初始化。
- 初始化一个类时,发现父类还没有进行初始化,先初始化父类。
- 虚拟机启动时,用户指定了要执行的主类时,先初始化这个主类。
- 遇到java.lang.invoke.MethodHandle实例最后的解析结果方法句柄时,没有初始化进行初始化操作。
开始初始化阶段,就是真正开始执行类中定义的Java程序代码(或者是字节码)