双亲委派机制通过加载路径锁定、定义权限隔离和类唯一性约束三重机制杜绝核心类被篡改:所有java.、javax.、sun.开头的类均由BootstrapClassLoader加载,子加载器无法定义此类,且类唯一性由“加载器+全限定名”绑定。

双亲委派机制通过加载路径锁定、定义权限隔离和类唯一性约束三重机制,从源头杜绝核心类被篡改的可能。
加载请求必须先交给 Bootstrap 加载器
所有以 java.、javax.、sun. 开头的类(如 java.lang.String),只要发起加载请求,无论来自应用代码还是自定义加载器,都会立即逐级向上委托:AppClassLoader → PlatformClassLoader → BootstrapClassLoader。Bootstrap 由 JVM 底层(C++)实现,只信任 $JAVA_HOME/lib 下的 java.base 等核心模块。它一旦发现该类已存在,就直接返回已加载的 Class 实例——你的同名类字节码甚至不会被读取。
非 Bootstrap 加载器无法定义核心包下的类
JVM 在 defineClass() 阶段内置强制校验:
- 若当前加载器不是 Bootstrap,且全限定名以
java.、javax.或sun.开头,直接抛出SecurityException - 这个校验不依赖委派逻辑,但双亲委派让它几乎不可能被触发——因为正常流程下,这类请求根本不会落到子加载器的
defineClass()方法里 - 即使重写
loadClass()强行跳过委派,JVM 仍会在定义阶段拒绝,而非静默失败
类的唯一性由“加载器 + 全限定名”共同决定
JVM 不把类名当唯一标识,而是将“类的全限定名”与“加载它的类加载器实例”绑定为一个整体:
立即学习“Java免费学习笔记(深入)”;
- 你用自定义加载器强行加载一个
java.lang.String,它和 Bootstrap 加载的String是两个完全独立的类型 - 二者无法赋值、无法转型、调用
equals()会抛ClassCastException - 这种隔离是运行时天然形成的命名空间屏障,不是靠语法或配置控制
系统加载器只做转发,不参与核心类定义
AppClassLoader 和 PlatformClassLoader 对核心类的处理极简干净:
- 收到
java.lang.*类请求 → 立即调用findSystemClass(name) - 该方法是 JVM 提供的白名单接口,只响应受信包,对非法请求返回
null或直接抛异常 - 它们绝不从本地 classpath 读取字节码,也绝不调用自己的
findClass()


















