类初始化和类加载

一、类的生命周期

类从被加载到内存到被卸载,经历了以下几个阶段:

1
加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载

其中:验证、准备和解析这三个阶段可以统称为连接。

类的生命周期

二、类加载全过程

JVM 从 .class 文件到可以使用,大致分为 5 个阶段

1
加载 → 验证 → 准备 → 解析 → 初始化

2.1 加载(Loading)

做什么:

  • 根据类的全类名(如 com.xxx.User)找到 .class 文件
  • 读取字节码
  • 在内存中生成一个 Class 对象(方法区)

关键点:

  • 不一定从磁盘加载(也可以网络、动态生成)
  • 类加载器 ClassLoader 完成

2.2 验证(Verification)

做什么:

  • 校验Class文件的字节流信息是否合法,保证不会危害 JVM

典型检查:

  • 文件格式是否正确
  • 是否符合 JVM 规范
  • 是否有非法指令

可以理解为:安全检查

验证阶段主要由四个检验阶段组成:

  • 文件格式验证(Class 文件格式检查)
  • 元数据验证(字节码语义检查)
  • 字节码验证(程序语义检查)
  • 符号引用验证(类的正确性检查)

2.3 准备(Preparation)

做什么:

  • 类变量(static变量)分配内存
  • 设置 默认初始值

⚠️ 注意:

1
static int a = 10;

在准备阶段:

1
a = 0   // 不是10!

这里只是“分配 + 默认值”,不是赋值

2.4 解析(Resolution)

做什么:

  • 将常量池中的 符号引用 → 直接引用

举例:

1
User u = new User();
  • 符号引用:字符串 “User”
  • 解析后:内存地址

可以理解为:“找地址”

2.5 初始化(Initialization)🔥重点

做什么:

  • 执行初始化方法 <clinit>()
  • 真正给 static 变量赋值
  • 执行 static 代码块

例如:

1
2
3
4
static int a = 10;
static {
a = 20;
}

初始化后:

1
a = 20

三、类初始化

3.1 什么是类初始化?

就是执行:

1
<clinit>() 方法

它由:

  • 静态变量赋值
  • static代码块

按顺序合并生成

3.2 类什么时候会初始化?(🔥)

会触发初始化的情况

  1. new对象
1
new User();
  1. 访问类的静态变量(非final)
1
User.a;
  1. 调用静态方法
1
User.test();
  1. 反射
1
Class.forName("User");
  1. 初始化子类(会先初始化父类)

  2. JVM启动时的主类

不会触发初始化

  1. 访问 static final 常量
1
static final int a = 10;

编译期已放入常量池

  1. 通过数组定义类
1
User[] arr = new User[10];

只是创建数组

  1. 访问父类的静态变量(通过子类)
1
Child.a;

只初始化父类

四、类加载 vs 类初始化(核心区别)

对比点 类加载 类初始化
范围 Loading ~ Resolution Initialization
是否执行代码 ❌ 不执行 ✅ 执行static代码
static变量 默认值 赋真实值
是否必须执行 不一定 只有触发才执行

五、一个经典执行顺序例子🔥

1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
static int a = 1;
static {
System.out.println("A init");
}
}

class B extends A {
static int b = 2;
static {
System.out.println("B init");
}
}

执行:

1
new B();

输出:

1
2
A init
B init

说明:

  • 先初始化父类
  • 再初始化子类

六、面试高频总结

可以这样答👇:

JVM类的生命周期包括加载、验证、准备、解析、初始化、使用和卸载七个阶段。
JVM类加载分为五个阶段:加载、验证、准备、解析、初始化。
其中初始化阶段会执行类的 <clinit> 方法,对静态变量进行赋值并执行 static 代码块。
类初始化是在首次主动使用时触发,比如 new对象、访问静态变量、调用静态方法、反射等。
类加载只是把类加载进内存,而初始化才是真正执行类中的代码。