ClassLoader(类加载器)
ClassLoader(类加载器)
背景
-
JVM
定义
- ClassLoader 是 JVM 提供的类加载机制(也是具体实现类的统称),核心作用是:将硬盘上的 .class 文件(字节码)加载到 JVM 内存中,并生成对应的 Class 对象,让程序能使用该类(比如
new实例、调用静态方法)
ClassLoader 的核心作用
- 加载:查找并读取 .class 文件到内存;
- 链接:验证(校验字节码合法性)→ 准备(为静态变量分配内存)→ 解析(将符号引用转为直接引用);
- 初始化:执行静态代码块、初始化静态变量(类的生命周期核心步骤);
- 双亲委派(Parent Delegation Model):ClassLoader 最核心的设计原则
JVM 内置的 ClassLoader 分类(核心)
| 类加载器类型 | 作用 | 加载范围 |
|---|---|---|
| 启动类加载器(Bootstrap) | 最顶层的类加载器,由 C/C++ 实现(无对应的 Java 类) | JRE/lib/rt.jar(核心类,如 java.lang.*) |
| 扩展类加载器(Extension) | 继承自 Bootstrap,Java 实现 | JRE/lib/ext/*.jar(扩展类) |
| 应用程序类加载器(Application) | 也叫系统类加载器,继承自 Extension,Java 实现 | 项目的 classpath 下的类(自己写的代码、第三方依赖) |
- 补充:自定义类加载器
- 如果需要加载非 classpath 下的类(比如加载网络上的 .class 文件、加密的 .class 文件),可以继承
java.lang.ClassLoader重写findClass()方法,实现自定义加载逻辑。
- 如果需要加载非 classpath 下的类(比如加载网络上的 .class 文件、加密的 .class 文件),可以继承
核心机制:双亲委派模型(Parent Delegation Model)(重点)
-
定义:当一个类加载器收到类加载请求时,不会先自己加载,而是先把请求委托给父类加载器,直到传递到顶层的 Bootstrap 加载器;只有父类加载器无法加载该类(找不到对应的 .class 文件),子类加载器才会自己尝试加载。
-
工作流程:
1
2
3
4
5
6graph TD
A[应用程序类加载器] -->|委托加载| B[扩展类加载器]
B -->|委托加载| C[启动类加载器]
C -->|找不到 com.example.MyClass| B
B -->|找不到 com.example.MyClass| A
A -->|加载 classpath 下的 com/example/MyClass.class| D[生成 Class 对象] -
为什么要设计双亲委派?
- 核心目的:保证类加载的安全性,避免核心类被篡改(比如自己写一个
java.lang.String类,双亲委派会优先用 Bootstrap 加载核心库的 String,而非自定义的,防止恶意替换); - 避免类重复加载:同一个类只会被一个类加载器加载一次,保证内存中只有一份 Class 对象。
- 核心目的:保证类加载的安全性,避免核心类被篡改(比如自己写一个
总结
- ClassLoader 核心是将 .class 文件加载到 JVM 内存生成 Class 对象,JVM 内置 Bootstrap/Extension/Application 三层加载器;
- 双亲委派模型是核心设计,优先委托父类加载器加载,保证核心类安全、避免类重复加载;
- 类只有 “主动使用” 时才会加载,常见问题需区分
ClassNotFoundException(加载不到文件)和NoClassDefFoundError(运行时缺失); - 自定义类加载器可实现热部署、插件化、加密加载等高级功能。