双亲委派模型是java类加载器默认协作策略,核心为“先向上委托、失败再回退加载”,旨在防止核心类被替换和避免同一类重复加载;其通过classloader.loadclass()方法的默认实现体现,严格遵循委托链查找类,并由父加载器优先加载。

双亲委派模型是 Java 类加载器协作加载类的默认策略,它不靠 JVM 强制约束,而是由 ClassLoader.loadClass() 方法的默认实现所体现。它的本质是“先向上委托、失败再回退加载”,核心目标就两个:防止核心类被替换、避免同一类被重复加载。
它是怎么工作的
当某个类加载器(比如应用类加载器)收到加载 java.util.ArrayList 的请求时,并不会立刻去 classpath 查找,而是按以下顺序执行:
- 先检查自己是否已加载过这个类;如果已加载,直接返回
Class对象 - 若未加载,将请求交给父加载器(如扩展类加载器),父加载器再交其父(启动类加载器)
- 启动类加载器在
$JAVA_HOME/jre/lib/rt.jar中找到ArrayList,成功加载并返回 - 后续所有父加载器都跳过,子加载器不再尝试加载
如果请求的是一个自定义类(如 com.example.User),启动和扩展类加载器都找不到,最终由应用类加载器在 classpath 下定位并加载。
它解决的关键问题
双亲委派不是为了“让代码更优雅”,而是为了解决真实运行中会崩溃的底层问题:
-
防篡改核心类:假设你写了一个
java.lang.String放进 classpath,没有双亲委派,应用类加载器可能把它加载进来,导致整个 JVM 行为异常;有了它,请求一上来就被启动类加载器截获并加载官方版本,你的类根本没机会生效 -
杜绝 ClassCastException 隐患:同一个类名(如
org.apache.commons.io.IOUtils)被两个不同加载器分别加载,JVM 会认为这是两个完全无关的类,哪怕字节码一模一样,也无法强制转型——双亲委派确保它只被最上层能加载它的加载器加载一次 -
自然形成类可见性边界:父加载器加载的类对子加载器可见(比如应用代码能直接用
java.lang.Object),但反过来不行;这种单向可见性依赖委派链天然建立,不需要额外配置
它的实际体现就在 loadClass 方法里
翻开 java.lang.ClassLoader 源码,loadClass(String name, boolean resolve) 的逻辑非常直白:
- 调用
findLoadedClass(name)查缓存 - 非空则返回;为空则优先调
parent.loadClass(...) - 父加载器抛出
ClassNotFoundException时,才调findClass(name)自己动手
这个流程就是双亲委派的全部骨架——没有魔法,只有清晰的委托与 fallback。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











