
一、类的生命周期
当我们在代码第一次使用某个类时,JVM 并不是把项目里所有的类一下子全加载进来,而是按需加载(Lazy Loading)。
一个类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期将会经历七个阶段:
加载 (Loading) -> 验证 (Verification) -> 准备 (Preparation) -> 解析 (Resolution) -> 初始化 (Initialization) -> 使用 (Using) -> 卸载 (Unloading)
其中,验证、准备、解析这三个部分统称为连接 (Linking)。接下来,我们逐一拆解核心的前五个阶段。
二、加载阶段
核心任务:把 .class 文件读入内存,并创建一个入口。
在这个阶段,JVM 需要完成三件事:
- 获取二进制字节流:通过一个类的全限定名(Package + Class Name)来获取定义此类的二进制字节流。来源非常灵活。可以是本地磁盘、ZIP 包(JAR/WAR)、网络(Applet)、甚至是运行时计算生成的(动态代理 Proxy)。
- 转化数据结构:将这个字节流所代表的静态存储结构转化为方法区(Method Area)的运行时数据结构
- 生成 Class 对象:在内存(堆 Heap)中生成一个代表这个类的
java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
本阶段产物:内存中多了一个 Class 对象(如 User.class)。
三、连接阶段
这一步是将已经读入内存的字节码,处理成 JVM 能直接使用的状态。它包含三个子步骤:
3.1 验证 (Verification)
目的:安检。确保被加载的类的正确性,保证它不会危害虚拟机自身的安全。
- 文件格式验证:检查魔数(
0xCAFEBABE)、版本号等。 - 元数据验证:语义检查。例如:这个类是否有父类?是否继承了不允许被继承的类(final 类)?
- 字节码验证:最复杂的一步。通过数据流分析,确保程序逻辑合法(例如:不会出现类型转换错误,不会跳转到不存在的指令等)。
- 符号引用验证:确保该类引用的其他类、方法、字段真实存在。
3.2 准备 (Preparation) —— 核心考点
目的:占位。为类的静态变量 (static) 分配内存,并设置默认初始值。
这里有两个极易混淆的概念,请务必区分:
- 仅限静态变量:此时只处理
static修饰的变量。实例变量(非 static)是随着对象实例化时才分配的。- 因为此时尚未执行任何 Java 代码。把 123 赋值给
value的指令是放在后面的'初始化'阶段执行的。
- 因为此时尚未执行任何 Java 代码。把 123 赋值给



