该文章为知识总结的文章,如果是初学者,建议先从专栏学习:JVM专栏
一、类的加载过程
分为三大阶段
-
加载:查找并且加载类的二进制数据
-
链接:
-
验证:确保被加载类的正确性
-
准备:为类的静态变量分配内存,并将其初始化为默认值
-
解析:把类中的符号引用转换为直接引用
-
-
初始化:执行构造方法
二、加载
类加载过程的第一步,主要完成下面3件事情:
- 通过全类名获取定义此类的二进制字节流
- 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
- 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口
一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 loadClass()
方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。
三、验证
主要目的:检查输入的字节流。为了确保当前加载的Class字节流符合虚拟机的要求,不会危害到虚拟机
检验动作
- 文件格式验证。判断当前字节流是否符合Class文件格式要求。
- 原数据验证。语义分析,判断数据类型是否符合Java语言规范
- 字节码验证。判断方法是否符合Java语言规范
- 符号引用验证。判断能否找到所引用的类
四、准备
目的:给类中静态变量赋予初值,其他的变量随着类的初始化,跟类存放在堆中
五、解析
目的:将常量池中的符号引用变成直接引用
六、初始化
目的:初始化是类加载的最后一步,初始化阶段是执行类构造器 <clinit> ()方法的过程
七、卸载
卸载类即该类的Class对象被GC。
卸载类需要满足3个要求:
- 该类的所有的实例对象都已被GC,也就是说堆不存在该类的实例对象。
- 该类没有在其他任何地方被引用
- 该类的类加载器的实例已被GC
所以,在JVM生命周期类,由jvm自带的类加载器加载的类是不会被卸载的。但是由我们自定义的类加载器加载的类是可能被卸载的。