
加载阶段
加载阶段是指通过完全限定名查找Class文件二进制数据并将其加载进内存的过程。大体流程会分为三步:
- ①通过完全限定名查找定位
.class文件,并获取其二进制字节流数据 - ②把字节流所代表的静态存储结构转换为运行时数据结构
- ③在堆中间中为其创建一个
Class对象,作为程序访问这些数据的入口
链接阶段
"验证、准备、解析" 是 Java 类加载系统中 链接(Linking)阶段 的三个重要子阶段。
🧩 一、验证(Verification)
目标: 保证字节码文件(.class)的合法性与安全性,防止虚拟机被破坏。
作用: 检查类文件是否符合 JVM 规范,确认不会造成安全问题。

主要检查内容:
| 验证类型 | 检查内容 | 举例 |
|---|---|---|
| 文件格式验证 | .class 文件结构是否正确 |
魔数、常量池、字段表是否符合规范 |
| 元数据验证 | 类的继承、实现关系是否合法 | final 类不能被继承 |
| 字节码验证 | 指令逻辑是否安全 | 操作数栈不会越界、类型匹配正确 |
| 符号引用验证 | 常量池中引用是否有效 | 方法、字段是否存在且可访问 |
👉 通俗理解: 验证阶段就像机场安检,确保行李没问题(类文件没错)才能上飞机(进入 JVM 运行环境)。
⚙️ 二、准备(Preparation)
目标: 为类变量(static 修饰的变量)分配内存,并设置默认初始值。
此时还不会执行任何初始化代码或赋值语句。
主要特点:
- 只处理类变量(静态变量),实例变量不管。
- 分配的内存位于方法区(JDK 8 后是元空间)。
- 默认值初始化(例如
int→ 0,boolean→ false,reference→ null)。
举例说明:
arduino
public class Demo {
static int a = 10;
static final int b = 20;
}
- 在 准备阶段 :
a = 0(分配内存并赋默认值)
b = 20(因为是编译期常量,直接赋值)
👉 通俗理解: 准备阶段就是 JVM 给静态变量"预留好房间",先放默认值进去,具体装修(赋值)在初始化阶段再做。
🔗 三、解析(Resolution)
目标: 把类中的符号引用(Symbolic Reference)转换为直接引用(Direct Reference)。
什么是符号引用?
符号引用是一种用字符串或索引描述目标的方式,比如:
- 类名:
java/lang/String - 字段:
FieldRef #5 - 方法:
MethodRef #10
JVM 在解析阶段会根据这些符号引用,去查找实际的类、方法或字段在内存中的位置。
解析的几种类型:
-
类或接口解析
- 把符号类名转换为对应的
Class对象。
- 把符号类名转换为对应的
-
字段解析
- 确定字段在内存布局中的具体位置。
-
方法解析
- 确定具体的方法实现。
-
接口方法解析
- 解析接口方法的具体实现(常见于动态绑定场景)。
👉 通俗理解: 解析阶段就像"联系人解析",把通讯录里的"张三"换成他的手机号(内存地址),方便 JVM 快速调用。
🧠 四、总结对比
| 阶段 | 主要任务 | 是否分配内存 | 是否执行代码 | 举例 |
|---|---|---|---|---|
| 验证(Verify) | 检查类文件安全性 | 否 | 否 | 检查格式、继承关系、栈安全 |
| 准备(Prepare) | 为静态变量分配内存并赋默认值 | ✅ 是 | 否 | static int a = 0 |
| 解析(Resolve) | 将符号引用替换为直接引用 | 否 | 否 | 把"方法名"替换为实际地址 |