题目
Java类加载机制与双亲委派模型解析
信息
- 类型:问答
- 难度:⭐⭐
考点
类加载机制,双亲委派模型,类加载器
快速回答
Java类加载机制分为加载、验证、准备、解析、初始化五个阶段。双亲委派模型工作原理:
- 类加载请求优先委派给父加载器处理
- 父加载器无法完成时才由子加载器尝试加载
- 加载器层次:Bootstrap → Extension → Application → Custom
核心作用:
- 避免重复加载,确保类唯一性
- 防止核心API被篡改(安全机制)
- 保证Java程序稳定运行
一、类加载机制完整流程
JVM加载类的生命周期包含五个阶段:
- 加载(Loading):查找字节码文件并创建Class对象
- 验证(Verification):检查字节码安全性(文件格式、元数据等)
- 准备(Preparation):为静态变量分配内存并赋默认值(如int=0)
- 解析(Resolution):将符号引用转换为直接引用
- 初始化(Initialization):执行静态代码块和静态变量赋值
注意:解析阶段可能在初始化之后发生(支持动态绑定)
二、双亲委派模型工作原理
// 类加载器加载逻辑伪代码
protected Class<?> loadClass(String name, boolean resolve) {
synchronized (getClassLoadingLock(name)) {
// 1. 检查是否已加载
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// 2. 委托父加载器
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 3. 父加载器为null表示Bootstrap加载器
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
// 4. 父加载器无法完成时自行加载
if (c == null) {
c = findClass(name);
}
}
return c;
}
}加载器层次结构:
- Bootstrap ClassLoader:加载JRE/lib核心库(C++实现)
- Extension ClassLoader:加载JRE/lib/ext扩展库
- Application ClassLoader:加载classpath用户类
- Custom ClassLoader:用户自定义加载器
三、双亲委派模型的核心作用
- 避免类重复加载:父加载器已加载的类,子加载器不会重复加载
- 保护核心API:防止用户自定义java.lang.Object等核心类
- 安全隔离:不同加载器加载的类被视为不同组件
四、破坏双亲委派的场景
- SPI机制:JDBC等服务接口由Bootstrap加载,实现类需反向委派(使用线程上下文加载器)
- 热部署:OSGi模块化系统为每个Bundle创建独立加载器
- 自定义加载需求:Tomcat为每个Web应用创建WebappClassLoader
五、最佳实践与常见错误
最佳实践:
- 自定义加载器应重写findClass()而非loadClass()
- 需要隔离加载环境时(如插件系统)才使用自定义加载器
- SPI场景使用
Thread.currentThread().getContextClassLoader()
常见错误:
- 循环依赖导致
ClassCircularityError - 不同加载器加载的类强制转换失败(
ClassCastException) - 未考虑父加载器缓存导致重复加载
六、扩展知识:类卸载条件
- 该类所有实例已被GC
- 加载该类的ClassLoader实例已被GC
- 该类对应的java.lang.Class对象无引用
注意:由Bootstrap加载器加载的类通常不会被卸载