双亲委派机制通过加载权上收和定义权隔离确保核心类不可篡改:加载请求逐级委托至bootstrap加载器,其仅从$java_home/lib可信路径加载;非bootstrap加载器定义java.*类时直接抛securityexception;类唯一性由“加载器+全限定名”决定,强行加载同名类将产生无法互操作的独立类型。

双亲委派机制通过“加载权上收”和“定义权隔离”两层硬性约束,确保 java.lang.* 等核心类无法被用户代码篡改或替换。
加载请求必须先交给 Bootstrap 加载器
当任意类加载器(如 AppClassLoader)收到 java.lang.String 的加载请求时,不会查找本地 classpath 或 jar 文件,而是立即逐级向上委托:App → Platform(Java 9+)→ Bootstrap。Bootstrap 加载器由 JVM 底层(C++)实现,只信任 $JAVA_HOME/lib 下的 java.base 模块等可信路径。它一旦发现该类在核心模块中已存在,就直接返回已加载的 Class 实例,你的自定义 String 类连字节码都不会被读取。
非 Bootstrap 加载器无法定义 java.* 包下的类
JVM 在 defineClass() 阶段内置包级校验:如果当前加载器不是 Bootstrap,且尝试定义的类全限定名以 java.、javax. 或 sun. 开头,直接抛出 SecurityException。这个校验不依赖委派逻辑,但双亲委派让它几乎不可能被触发——因为正常流程下,这类请求根本不会落到自定义加载器的 defineClass() 上。
类的唯一性由“加载器 + 全限定名”共同决定
即使绕过委派强行加载一个同名类(例如用非法手段让自定义加载器调用 defineClass),JVM 仍视其为完全独立的类型:
-
new java.lang.String()创建的对象,类型是 Bootstrap 加载的Class - 你“造出来”的
java.lang.String是另一个Class实例 - 二者无法赋值、无法转型、调用
equals()会抛ClassCastException
这种隔离不是靠语法检查,而是类加载器命名空间天然形成的运行时屏障。
系统类加载器只做转发,不参与定义
AppClassLoader 和 PlatformClassLoader 对 java.* 类的处理逻辑非常干净:只调用 findSystemClass(name) 向 Bootstrap 请求,绝不尝试从本地路径读取字节码,也绝不调用自己的 findClass()。这个方法是 JVM 内部实现的白名单接口,只响应受信包,对非法请求返回 null 或抛异常,不留注入入口。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











