双亲委派模型
类加载器的 双亲委派模型(Parent Delegation Model) 是 Java 虚拟机中类加载机制的一部分,主要用于保证 Java 平台的安全性和类加载的一致性。
🧭 一、什么是双亲委派模型?
双亲委派模型的核心思想是:
一个类加载器在接收到类加载请求时,先把这个请求委托给它的“父类加载器”去完成;只有在父类加载器无法完成这个请求(即找不到类)时,子类加载器才会尝试自己去加载。
🏗️ 二、类加载器结构
Java 默认的类加载器结构如下:
Bootstrap ClassLoader (启动类加载器)
↑
Extension ClassLoader(扩展类加载器)
↑
Application ClassLoader(应用类加载器)
↑
Custom ClassLoader(自定义类加载器)🔄 三、类加载过程流程图
加载某个类 -> 先请求父加载器加载
↓
父加载器能加载? → 是 → 使用父加载器加载
→ 否 → 当前加载器自己加载📦 四、为什么使用双亲委派模型?
- 避免类的重复加载
如果父类已经加载过了某个类,子类加载器就不会再加载,避免了类的冗余和冲突。 - 保护核心 API
自定义类无法伪造java.lang.String等核心类,因为请求会优先由启动类加载器处理,从而保证了核心类的唯一性和安全性。 - 保证类加载的一致性
比如当多个类加载器加载相同类时,双亲委派机制能保证这些类具有相同的版本,避免运行时冲突。
🔧 五、自定义类加载器如何打破双亲委派(可选)
某些场景(如热部署、Tomcat、OSGi 插件系统)需要打破双亲委派:
- 自定义类加载器可以 先尝试自己加载,然后再委托父类(称为**“打破双亲委派”**)。
- 常见的方式是重写
loadClass()方法,不直接调用super.loadClass(),而是改为先findClass()。
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 不委托父加载器,直接自己找
Class<?> c = findClass(name);
if (resolve) {
resolveClass(c);
}
return c;
}⚠️ 注意:打破双亲委派机制要非常小心,可能引发类冲突或安全问题。
📘 六、示例:类加载器加载顺序
public class TestClassLoader {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = TestClassLoader.class.getClassLoader();
while (classLoader != null) {
System.out.println(classLoader);
classLoader = classLoader.getParent();
}
// 最后输出 null,表示 Bootstrap ClassLoader
}
}输出示例(JDK 8):
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null✅ 七、小结
| 类加载器 | 作用 | 加载内容 |
|---|---|---|
| Bootstrap ClassLoader | 核心类加载器(C++实现) | 加载 JDK 的核心类(rt.jar) |
| Extension ClassLoader | Java 扩展类加载器(Java实现) | 加载 jre/lib/ext 下的类 |
| AppClassLoader | 应用类加载器 | 加载应用 classpath 下的类 |
| 自定义 ClassLoader | 用户定义加载器 | 加载指定路径或网络类 |
双亲委派模型
https://liuyuhe666.github.io/2025/07/06/双亲委派模型/