双亲委派模型

类加载器的 双亲委派模型(Parent Delegation Model) 是 Java 虚拟机中类加载机制的一部分,主要用于保证 Java 平台的安全性和类加载的一致性。

🧭 一、什么是双亲委派模型?

双亲委派模型的核心思想是:

一个类加载器在接收到类加载请求时,先把这个请求委托给它的“父类加载器”去完成;只有在父类加载器无法完成这个请求(即找不到类)时,子类加载器才会尝试自己去加载。

🏗️ 二、类加载器结构

Java 默认的类加载器结构如下:

1
2
3
4
5
6
7
Bootstrap ClassLoader (启动类加载器)

Extension ClassLoader(扩展类加载器)

Application ClassLoader(应用类加载器)

Custom ClassLoader(自定义类加载器)

🔄 三、类加载过程流程图

1
2
3
4
加载某个类 -> 先请求父加载器加载

父加载器能加载? → 是 → 使用父加载器加载
→ 否 → 当前加载器自己加载

📦 四、为什么使用双亲委派模型?

  1. 避免类的重复加载
    如果父类已经加载过了某个类,子类加载器就不会再加载,避免了类的冗余和冲突。
  2. 保护核心 API
    自定义类无法伪造 java.lang.String 等核心类,因为请求会优先由启动类加载器处理,从而保证了核心类的唯一性和安全性。
  3. 保证类加载的一致性
    比如当多个类加载器加载相同类时,双亲委派机制能保证这些类具有相同的版本,避免运行时冲突。

🔧 五、自定义类加载器如何打破双亲委派(可选)

某些场景(如热部署、Tomcat、OSGi 插件系统)需要打破双亲委派:

  • 自定义类加载器可以 先尝试自己加载,然后再委托父类(称为**“打破双亲委派”**)。
  • 常见的方式是重写 loadClass() 方法,不直接调用 super.loadClass(),而是改为先 findClass()
1
2
3
4
5
6
7
8
9
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 不委托父加载器,直接自己找
Class<?> c = findClass(name);
if (resolve) {
resolveClass(c);
}
return c;
}

⚠️ 注意:打破双亲委派机制要非常小心,可能引发类冲突或安全问题。

📘 六、示例:类加载器加载顺序

1
2
3
4
5
6
7
8
9
10
11
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):

1
2
3
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/双亲委派模型/
作者
Liu Yuhe
发布于
2025年7月6日
许可协议