双亲委派模型通过自顶向下委托、自底向上加载的硬性流程,确保java.*等核心类仅由BootstrapClassLoader加载,从根本上防止篡改;其依赖loadClass()中“先父后己”逻辑及JVM对受保护包的强制校验(如SecurityException),是Java沙箱安全机制的执行基础。

双亲委派模型通过“优先由顶层加载器加载核心类”的硬性流程,从机制层面切断了用户代码篡改 java.* 等关键类的可能路径。
启动类加载器垄断核心类加载权
所有以 java. 开头的类(如 java.lang.String、java.util.ArrayList)都存放在 $JAVA_HOME/jre/lib/rt.jar(或 Java 9+ 的 modules)中。这些路径仅被启动类加载器(Bootstrap ClassLoader)识别,而它由 JVM 用 C++ 实现,无法被 Java 层代码替换或绕过。当加载请求到达时,无论哪个类加载器发起,都会先层层委托到它——只要它能定位并加载成功,下级加载器就完全没机会介入。
类加载结果具有唯一性和不可覆盖性
JVM 规定:同一个类加载器对同一个全限定名的类,只会成功加载一次;不同类加载器加载的同名类,在 JVM 中视为完全不同的类型,互不兼容。这意味着:
- 即使你在项目里新建
java.lang.String类,编译能通过,但运行时一触发加载,启动类加载器早已把官方String加载进内存; - 你的自定义
String根本不会被加载——因为委托链在顶层就返回了已加载的 Class 对象; - 若强行用自定义类加载器跳过委派(比如重写
loadClass),JVM 在链接阶段会校验签名和包权限,对java.*包下的类直接抛出SecurityException。
沙箱安全机制依赖该流程落地
双亲委派不是孤立规则,而是 Java 安全模型的执行基础。它配合字节码验证、包访问控制(java.lang.SecurityManager 已弃用但逻辑仍在)、模块系统(JPMS)共同构成防护网。例如:
立即学习“Java免费学习笔记(深入)”;
- 第三方库试图反射修改
java.lang.System的静态字段?失败——因为该类由启动类加载器加载,其ClassLoader返回null,任何非启动加载器都无法获取其可写的运行时类对象; - Web 容器中多个应用各自打包了不同版本的
javax.servlet.*?扩展类加载器(或平台类加载器)统一加载,避免冲突,也防止某个应用偷偷替换 Servlet API 行为。
破坏委派必须显式越权,且受严格限制
虽然可通过线程上下文类加载器(TCCL)或重写 loadClass 打破委派,但这类操作仅对非 java.* 和非 javax.*(受限包)生效。JVM 内部对核心包有硬编码保护,比如 ClassLoader.checkPackageAccess 方法会在加载前强制校验调用栈中是否存在非法包访问。任何试图加载 java.* 的自定义行为,都会在 findBootstrapClassOrNull 或验证阶段被拦截。


















