Java类加载机制深度解析:从.class文件到JVM虚拟机
1. 类加载的全景流程
Java类从磁盘上的.class
文件到内存中的可执行对象,需经历完整的加载生命周期:
.class文件 → 加载(Loading) → 链接(Linking) → 初始化(Initialization) → 使用(Using) → 卸载(Unloading)
2. 类加载的三大阶段详解
2.1 装载阶段(Loading)
核心任务:查找并加载类的二进制数据
具体工作:
- 通过全限定名获取.class文件字节流
- 将字节流转换为方法区的运行时数据结构
- 在堆中生成对应的
Class
对象(作为方法区数据的访问入口)
数据来源:
- 本地文件系统(常见)
- ZIP/JAR包(如第三方库)
- 网络动态加载(Applet)
- 运行时生成(动态代理)
2.2 链接阶段(Linking)
(1) 验证(Verification)
确保.class文件符合JVM规范:
- 文件格式验证:魔数0xCAFEBABE开头
- 元数据验证:语义分析(如是否继承final类)
- 字节码验证:栈帧类型约束
- 符号引用验证:常量池检查
案例:修改.class文件魔数将导致
ClassFormatError
(2) 准备(Preparation)
为类变量(static变量)分配内存并设置初始值:
- 基本类型:
0
/false
/null
等默认值 - 常量(static final)直接赋真实值
// 准备阶段后:
public static int value = 123; // value = 0
public static final int CONST = 456; // CONST = 456
(3) 解析(Resolution)
将符号引用转换为直接引用:
- 类/接口解析
- 字段解析
- 方法解析
// 符号引用 → 直接引用
invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
2.3 初始化阶段(Initialization)
执行类构造器()
方法的过程:
- 按顺序执行static变量赋值和static代码块
- 父类的``先于子类执行
- 线程安全(加锁同步)
public class InitDemo {static {System.out.println("静态块执行");