JVM 类加载子系统是什么?
类加载子系统(Class Loader Subsystem)是 JVM 负责 加载、链接和初始化 .class
文件的组件。它的主要作用是将字节码文件加载进 JVM 并准备执行。
类加载器(ClassLoader)是 字节码的搬运工,负责 找到、加载、解析和初始化字节码,最终让 JVM 执行它。
类加载子系统 = 类加载器 + 其他步骤
类加载子系统主要包括三个阶段:
- 加载(Loading) → 由类加载器完成,找到
.class
文件并加载到方法区。 - 链接(Linking) → 验证(检查字节码)、准备(分配静态变量)、解析(符号引用替换)。
- 初始化(Initialization) → 执行
static
代码块和静态变量赋值。
1. 为什么需要类加载子系统?
当你写一个 Java 类,比如:
public class Demo {public static void main(String[] args) {System.out.println("Hello JVM!");}
}
编译后会生成一个 Demo.class
文件,这个文件并不能直接运行,而是需要 JVM 加载 进内存,解析并执行,这就是 类加载子系统的作用。
2. 类加载子系统的主要任务
类加载子系统的作用主要包括:
- 加载(Loading):将
.class
文件从磁盘/网络/其他来源加载进 JVM。 - 链接(Linking):
- 验证(Verification):检查 class 字节码是否合法(避免恶意代码)。
- 准备(Preparation):为静态变量分配内存,赋默认值。
- 解析(Resolution):将符号引用替换为直接引用(将
String.class
转换为内存地址)。
- 初始化(Initialization):执行类的
static
代码块和static
变量初始化代码。
3. 类加载过程(深入细节)
(1) 加载(Loading)
JVM 通过 类加载器(ClassLoader) 将 .class
文件加载到内存,类信息存放在 方法区。
来源:
- 磁盘(如
C:\classes\Demo.class
) - 网络(如
http://example.com/Demo.class
) - 运行时生成(如动态代理
Proxy
)
示例:
Class<?> clazz = Class.forName("com.example.Demo");
这个调用会触发 Demo.class
加载。
(2) 连接(Linking)
加载完成后,JVM 需要确保类的正确性,并为其分配必要的内存。
✅ (a) 验证(Verification)
检查 .class
文件是否符合 JVM 规范,防止字节码攻击。
✅ (b) 准备(Preparation)
给 静态变量 分配内存并初始化默认值(不执行赋值语句)。
public class Test {static int a = 10;
}
- 准备阶段:
a = 0
(默认值) - 初始化阶段:
a = 10
(执行赋值)
✅ (c) 解析(Resolution)
将 符号引用(java/lang/String
)转换成 直接引用(指向方法区 String.class
的地址)。
(3) 初始化(Initialization)
真正执行 static
代码块 和 static
变量赋值。
public class Test {static int a = 10;static {System.out.println("Class initialized");}
}
- 赋值
a = 10
- 执行 static 代码块,打印
"Class initialized"
⚠ 类初始化的时机 只有第一次使用该类(创建对象、访问静态变量等)时,才会初始化:
Test t = new Test(); // 触发初始化
4. 类加载器(ClassLoader)
JVM 提供不同层次的类加载器:
- Bootstrap ClassLoader(启动类加载器)
- 加载核心类库(
rt.jar
) - 例:
java.lang.String
- 加载核心类库(
- Extension ClassLoader(扩展类加载器)
- 加载
lib/ext
目录下的类 - 例:
javax.crypto.Cipher
- 加载
- Application ClassLoader(应用类加载器)
- 加载 classpath 下的应用代码
- 例:
com.example.Demo
- 自定义 ClassLoader
- 通过
URLClassLoader
或defineClass
自定义类加载逻辑。
- 通过
示例:
ClassLoader classLoader = Test.class.getClassLoader();
System.out.println(classLoader); // AppClassLoader
5. 结论
- 类加载子系统 负责 将
.class
文件加载到 JVM,并执行必要的初始化操作。 - 类加载有 加载(Loading)、链接(Linking)和初始化(Initialization) 三个阶段。
- 类加载器 负责查找并加载
.class
文件,JVM 默认有 启动类加载器、扩展类加载器、应用类加载器,也可以自定义类加载器。
⚡ 总结一句话:
类加载子系统是 JVM 的入口,负责加载、校验和初始化类,使其能够被 JVM 运行。