1. 加载(Loading)
核心任务:
将字节码的二进制数据读入 JVM 内存。
触发条件:
首次主动使用类时(如 new
、访问静态字段/方法、反射等)。
被动引用(如通过子类引用父类的静态字段)不会触发加载。
2.验证(Verification)
检查字节码是否符合 JVM 规范(防止恶意代码)
包括:文件格式验证、元数据验证、字节码验证、符号引用验证。
3. 准备(Preparation)
为 静态变量 分配内存并赋 默认值(如
int
为0
,引用类型为null
)。
注意:static final
常量(编译期已知)会直接赋实际值(如 static final int x = 123
)。
4. 解析(Resolution)
将常量池中的 符号引用(如类名、方法名)转换为 直接引用(内存地址)。
可能延迟到首次使用时解析(如动态绑定的方法)。
5. 初始化(Initialization)
执行类的
<clinit>()
方法(由编译器生成)。
包含:
- 静态变量的显式赋值(如
static int x = 5;
)。 - 静态代码块(
static {}
)中的逻辑。 - 线程安全:JVM 会加锁确保只初始化一次。
触发条件(满足任意一条):
new
、静态方法/字段调用、反射调用(如Class.forName()
)。- 子类初始化时,若父类未初始化,会先触发父类初始化。
- JVM 启动时的主类(
main
方法所在类)。