您好,登录后才能下订单哦!
# 什么是双亲委派机制
## 目录
1. [引言](#引言)
2. [类加载器基础](#类加载器基础)
3. [双亲委派机制定义](#双亲委派机制定义)
4. [工作流程详解](#工作流程详解)
5. [实现原理分析](#实现原理分析)
6. [优势与设计意义](#优势与设计意义)
7. [打破双亲委派机制](#打破双亲委派机制)
8. [实际应用场景](#实际应用场景)
9. [常见问题与解决方案](#常见问题与解决方案)
10. [总结](#总结)
---
## 引言
在Java虚拟机(JVM)的类加载过程中,**双亲委派机制(Parent Delegation Model)** 是保证Java程序稳定运行的核心设计原则之一。该机制通过层次化的类加载器结构,有效解决了类重复加载、核心API被篡改等关键问题。本文将深入解析这一机制的实现原理、工作流程及其在Java生态中的重要意义。
---
## 类加载器基础
### 类加载器的作用
- 将.class文件加载到JVM内存
- 转换为方法区中的运行时数据结构
- 生成对应的`Class<?>`对象
### Java中的三类加载器
1. **Bootstrap ClassLoader**(启动类加载器)
- 加载`JAVA_HOME/lib`下的核心类库(如rt.jar)
- 唯一没有父加载器的加载器
2. **Extension ClassLoader**(扩展类加载器)
- 加载`JAVA_HOME/lib/ext`目录的扩展类
- 父加载器为Bootstrap
3. **Application ClassLoader**(应用程序类加载器)
- 加载用户类路径(ClassPath)上的类
- 父加载器为Extension
```java
// 查看类加载器示例
public class ClassLoaderDemo {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader()); // null (Bootstrap)
System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader()); // ExtClassLoader
System.out.println(ClassLoaderDemo.class.getClassLoader()); // AppClassLoader
}
}
“A class loader delegates the search for classes and resources to its parent class loader before attempting to find the class or resource itself.” —— Java官方文档
AppClassLoader
收到请求ExtClassLoader
ExtClassLoader
继续委派给BootstrapClassLoader
Bootstrap
尝试加载:
ExtClassLoader
尝试ExtClassLoader
尝试加载:
AppClassLoader
尝试AppClassLoader
在classpath中查找并加载graph TD
A[AppClassLoader] --> B[ExtClassLoader]
B --> C[BootstrapClassLoader]
C -->|加载失败| B
B -->|加载失败| A
ClassLoader.loadClass()
的典型实现:
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. 父加载器为空则尝试Bootstrap加载
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
if (c == null) {
// 4. 自行查找类
c = findClass(name);
}
}
return c;
}
}
安全性保障
避免重复加载
职责分离
当用户自定义java.lang.Object
类时:
1. 加载请求最终委派到BootstrapClassLoader
2. Bootstrap已加载过JRE中的Object类
3. 直接返回已加载的Class对象
4. 自定义类永远不会被加载
SPI服务发现(如JDBC驱动加载)
热部署需求
// 通过重写loadClass方法打破委派
public class CustomClassLoader extends ClassLoader {
@Override
protected Class<?> loadClass(String name, boolean resolve) {
// 1. 自定义逻辑优先处理
if (name.startsWith("com.special.")) {
return findClass(name);
}
// 2. 其他类仍走双亲委派
return super.loadClass(name, resolve);
}
}
graph BT
WebApp1[WebAppClassLoader] --> Common[CommonClassLoader]
WebApp2[WebAppClassLoader] --> Common
Common --> Shared[SharedClassLoader]
Shared --> Server[ServerClassLoader]
Server --> Bootstrap
@EnableAspectJAutoProxy(proxyTargetClass=true)
控制异常类型 | 触发阶段 | 常见原因 |
---|---|---|
ClassNotFoundException | 加载阶段 | 类文件不存在 |
NoClassDefFoundError | 链接阶段 | 类已加载但依赖缺失 |
// 热加载示例
public class HotSwap {
public static void main(String[] args) throws Exception {
while (true) {
CustomClassLoader loader = new CustomClassLoader();
Class<?> clazz = loader.loadClass("com.example.DynamicClass");
Object instance = clazz.newInstance();
clazz.getMethod("execute").invoke(instance);
Thread.sleep(5000);
}
}
}
双亲委派机制作为Java类加载体系的核心设计: - 通过层次化委派保证类加载的有序性 - 是Java安全模型的基石之一 - 在保持稳定性的同时允许通过特定方式扩展
随着模块化系统(JPMS)的引入,Java 9+对类加载机制进行了进一步优化,但双亲委派的基本思想仍是理解JVM类加载过程的关键所在。
最佳实践建议:在自定义类加载器时,除非有明确需求,否则应保持双亲委派机制的完整性。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。