虚拟机类加载过程简述
类的生命周期
如图:
这些阶段并非严格进行区分,因为有些阶段执行时,同时还会执行下一阶段的某些功能。
加载
加载,即将类加载到虚拟机中,其实这一阶段是为了后面的所有阶段做准备。
因为后面的操作都是对于方法区或者堆等内存进行操作,只有加载才是对字节码文件进行操作。
这里主要执行3个步骤:
- 使用类加载器,通过全限定名来获取该类的二进制字节流。
- 将该字节码文件所代表静态存储结构转化为存储在方法区的运行时数据结构
- 创建该类对应的java.lang.Class对象实例,(Hotspot将其存储在方法区),作为该类的各种数据入口。
验证
验证阶段存在多个模块的验证:
1. 文件格式验证——这里即对字节码文件进行验证,确保该字节码能正确加载进方法区。
2. 元数据验证——这里主要对加载进方法区的数据进行验证,确保每一个数据类型都是Java所支持的,而不存在有违规类型。
3. 符号引用验证——大概来讲,就是对方法区中的符号引用进行验证,确保在后面的解析阶段,能够使符号引用成功解析为直接引用。
4. 字节码文件验证——这一步最复杂,涉及很多,笔者也只是大概知道这里会对字节码记性语义、程序逻辑等进行验证。(但是,这里的验证也不能保证程序完全正确)
准备
准备阶段其实就是给类中静态变量进行分配内存和置为0值。
这里的静态变量包括static修饰和final static修饰的变量。两者有细微差别:
对于只有static修饰的变量:
准备阶段分配内存,并置为零值(这里的零值并不是初始化,而是想boolean变量默认为FALSE的意思)
同时使用final static修饰的变量:
不但会分配内存,而且会直接初始化(如 static final int i=5,那么在该阶段i将赋值为5)
解析阶段
解析阶段就是将符号引用转换为直接引用的过程。
初始化
此时虚拟机将自动收集静态代码块与赋值语句,成为一个可以成为类构造器的“方法”,它负责将赋值操作与今天代码块执行完毕。