一个类从被加载到虚拟机内存中,到卸载出内存,生命周期包括了:加载,验证,准备,解析,初始化,使用和卸载。大致的顺序可如下图:
关于类加载的全过程,也就是指加载,验证,准备,解析和初始化这五个阶段的具体操作。
加载(Loading)
首先我们要明白,加载是类加载的第一个阶段,而并非相同,加载的过程中,虚拟机所要进行如下操作:
- 通过一个类的全限定名来获取定义该类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表该类的java.lang.Class的对象,作为方法区这个类的各种数据的访问入口。
验证(Verification)
验证阶段,就是判断加载进内存的这个类是否符合JVM的编译规则,整体上来说,验证阶段会完成四个阶段的检验动作:文件格式验证,元数据验证,字节码验证,符号引用验证。
1.文件格式验证
验证字节流是否符合Class文件格式的规范,是否能被当前版本的虚拟机处理
2.元数据验证
第二阶段是对字节码的信息进行语义分析,保证其描述的信息符合java语言规范的要求,确保其不存在不符合Java语言规范的元数据信息
3.字节码验证
这一阶段,主要目的是通过数据流和控制流分析,确保程序语义合法,符合逻辑的。这个阶段会对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。
4.符号引用验证
这一阶段,就到了虚拟机将符号引用转化为直接引用的时候了,这个转化动作发生在连接的第三个阶段。
准备(Preparation)
准备阶段是正式为类变量分配内存并设置初始值的阶段,这些变量所使用的内存都会在方法区进行分配,要留意的是,这个时候进行内存分配的只是静态变量,不包括实例变量,实例变量会随着对象的实例化而随着对象一起分配在Java堆中。
解析 (Resolution)
前面提到的,常量池的符号引用替换成直接引用的过程,就是解析的过程。
初始化(Initialization)
初始化阶段作为类加载过程的最后一步,才真正开始执行类中定义的Java代码,在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,会根据程序员通过程序验证的主观计划去初始化类变量和其他资源。
以上就是类加载过程的大致介绍,主要参考来源——《深入了解Java虚拟机》(周志明著)