JVM 的类加载过程?
Java 中的类加载过过程分为三个阶段:
- 加载
- 链接
- 验证
- 准备
- 解析
- 初始化
这三个阶段怎么理解?
-
加载阶段: 查找并加载类的二进制数据(网络、jar 包、运行时生成等)。将类的
.class
文件中的二进制数据读入内存当中。将其放在方法区中,然后创建一个java.lang.Class
对象(存放于堆中)用于封装类在方法区的数据结构。 -
链接阶段: Java 类加载器对类进行验证、准备(分配内存、初始化默认值)和解析操作,将类与类之间的关系确定好(符号引用转直接引用),然后校验字节码。
- 验证:验证文件格式、元数据、字节码、二进制兼容性是否正确
- 准备:给类的静态变量分配内存,初始化为默认值。
- 解析:把类的符号引用转为直接引用
-
初始化阶段: 类加载过程的最后一步,初始化阶段是执行类构造器中
<clinit> ()
方法的过程。这里利用了一种懒加载的思想,所有 Java 虚拟机实现必须在每个类或者接口被 Java 程序首次主动使用才初始化。
知识扩展
什么是符号引用和直接引用?
符号引用: 是一种直接表示引用目标的符号名称。例如:类名、字段名、方法名等。符号引用和实际的内存地址无关,符号引用只是一个标识符。用于描述被引用者,也就是类似于变量名的东西。符号引用产生于编译期,存储于Class
文件。
直接引用: 是实际指向目标的内存地址。例如:类的实例、方法的字节码等。直接引用与内存地址直接相关,产生于运行期。
说白了,符号引用就相当于一个变量名;直接引用就相当于内存地址。