双亲委派模型是JVM默认的安全加载策略,非强制铁律;其核心是类加载器收到请求时先向上委派父加载器尝试加载,直至Bootstrap ClassLoader,仅当所有上级均无法加载时才由当前加载器执行加载。

双亲委派模型不是“必须遵守的铁律”,而是JVM默认采用的安全加载策略。它核心作用是防止核心类被篡改、避免类重复加载,但实际开发中很多场景恰恰需要绕过它——面试官问“如何打破”,重点不是背概念,而是说清为什么破、在哪破、怎么破。
双亲委派模型到底在委派什么?
当一个类加载器收到加载请求时,它不会立刻自己找.class文件,而是先把请求“往上递”:先让父加载器尝试;父不行,再让祖父加载器尝试;直到Bootstrap ClassLoader。只有所有上级都找不到,当前加载器才真正动手加载。
- Bootstrap ClassLoader:加载$JAVA_HOME/lib下的核心类(如
java.lang.Object),由C++实现,无Java对象对应 - Platform ClassLoader(原Extension):加载$JAVA_HOME/lib/ext或-Djava.ext.dirs指定路径的扩展类
- Application ClassLoader:加载CLASSPATH环境变量指定路径的类,也就是我们写的代码和第三方jar
- 自定义ClassLoader:继承
ClassLoader,可控制加载逻辑,是打破委派的关键出口
为什么要打破双亲委派?四个典型场景
不是为了炫技,而是现实需求倒逼机制调整:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Web应用隔离(如Tomcat):每个Web应用(war包)都有自己的
WEB-INF/lib和WEB-INF/classes。若严格委派,所有应用共用AppClassLoader,就会互相污染、版本冲突。Tomcat为每个应用创建独立的WebAppClassLoader,并优先自己加载,找不到再委派——本质是“反向委派” -
热部署与动态加载:Spring Boot DevTools、OSGi插件、IDE调试时替换class文件,都需要卸载旧类、加载新类。而Bootstrap/AppClassLoader不支持卸载,必须用自定义加载器,在
loadClass()里跳过super.loadClass()调用,直接走findClass() -
SPI机制(如JDBC驱动):
java.sql.Driver接口由Bootstrap加载,但MySQL驱动com.mysql.cj.jdbc.Driver在应用jar里,Bootstrap根本看不到。JDK用ServiceLoader配合线程上下文类加载器(TCCL):把AppClassLoader设为当前线程TCCL,让Bootstrap层代码能通过Thread.currentThread().getContextClassLoader()拿到子加载器去加载实现类 - 多版本库共存(微服务/插件系统):A模块依赖Spring 5,B模块依赖Spring 6。统一委派只会加载其中一个版本。解决方案是为每个模块分配独立ClassLoader,彼此隔离,互不干扰
怎么安全地打破它?两种主流方式
关键不是删代码,而是有意识地重写加载流程:
立即学习“Java免费学习笔记(深入)”;
-
重写
loadClass(String, boolean)方法:这是最直接的方式。标准做法是注释掉或跳过super.loadClass()调用,改为先调用findClass()尝试本地加载;失败后再按需委派(比如只对特定包名跳过委派) -
利用线程上下文类加载器(TCCL):不改动类加载器本身,而是在关键执行点(如JDBC
DriverManager初始化时)主动设置TCCL为应用类加载器。框架内部通过Thread.currentThread().getContextClassLoader()获取并使用它——这是一种“委托穿透”,比重写更轻量、更解耦
面试时容易踩的坑
别只说“重写loadClass就能破”,要体现深度:
- 误以为“打破=完全不用父加载器”:多数场景仍需部分委派(如加载
java.*类必须交给Bootstrap,否则会报错) - 忽略类卸载前提:只有自定义ClassLoader加载的类,在无引用后才可能被GC;Bootstrap/AppClassLoader加载的类几乎永不卸载
- 混淆
findClass()和defineClass():前者负责定位字节码(如读文件、解密、网络下载),后者才是真正把字节码转成Class对象的“临门一脚” - 没提安全风险:随意打破委派可能导致
java.lang.String被恶意替换,所以生产环境必须做白名单校验或签名验证

















