双亲委派模型指类加载器收到请求时优先委托父加载器加载,直至BootstrapClassLoader;若父加载器无法加载,子加载器才自行加载,以此保障类唯一性与安全性。

Java 类加载机制中的双亲委派模型,核心在于“优先委托父加载器尝试加载”,不是简单地“层层向上找”,而是通过明确定义的加载器层级和委托规则,保障类的唯一性与安全性。
什么是双亲委派模型
双亲委派模型(Parent Delegation Model)指当一个类加载器收到类加载请求时,它不会立即自己去加载,而是先将请求委派给父类加载器;父加载器再委派给自己的父加载器,直到最顶层的启动类加载器(Bootstrap ClassLoader)。只有当父加载器无法完成加载(即在它的搜索路径下找不到该类)时,子加载器才会尝试自己加载。
这里的“双亲”是历史叫法,实际是单向委托链:启动类加载器 → 扩展类加载器(Extension) → 应用程序类加载器(AppClassLoader) → 自定义类加载器。
为什么需要双亲委派
主要解决两个关键问题:
- 避免类重复加载:相同全限定名的类,由不同加载器加载会产生多个不兼容的 Class 对象。委派机制确保核心类(如 java.lang.Object)始终由 Bootstrap 加载,保证 JVM 内部一致性。
- 防止核心类被篡改:如果允许自定义加载器擅自加载 java.lang.String,就可能植入恶意逻辑。委派机制让核心类只能由可信的 Bootstrap 加载,从源头上加固安全边界。
双亲委派的典型流程
以加载 java.util.ArrayList 为例:
- 线程上下文类加载器(通常是 AppClassLoader)收到加载请求;
- 它调用 parent.loadClass("java.util.ArrayList"),委托给 ExtensionClassLoader;
- ExtensionClassLoader 同样委托给 BootstrapClassLoader;
- BootstrapClassLoader 在 $JAVA_HOME/jre/lib 下找到 rt.jar 中的 ArrayList.class,成功加载并返回;
- 后续加载器不再执行自己的 findClass(),整个链路终止。
如何打破双亲委派
某些场景需绕过该模型,例如:
- SPI 机制(如 JDBC 驱动):接口由 Bootstrap 加载,但实现类在应用 classpath,必须由线程上下文类加载器(AppClassLoader)加载——此时需主动获取并使用 TCCL 调用 loadClass()。
- 热部署/模块化容器(如 OSGi、Tomcat):每个 Web 应用需隔离加载自己的 commons-lang 等 jar,不能共享父加载器的版本。Tomcat 为此自定义了 WebAppClassLoader,重写 loadClass() 方法,优先本地加载,失败后再委派。
打破的关键动作是:重写 loadClass(String name, boolean resolve),跳过 super.loadClass(),直接调用 findClass() 或指定加载器加载。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











