loadClass 方法强制执行“先委托父加载器,失败再自行查找”的双亲委派逻辑;自定义 java.lang.String 无效,因 BootstrapClassLoader 优先加载 rt.jar 中的版本并阻止后续加载;破坏该机制会导致 LinkageError、类隔离失效及安全沙箱崩溃。

loadClass 方法里藏着的“先问爹,再问爷”逻辑
loadClass 是 ClassLoader 的核心入口方法,它的默认实现(在 java.lang.ClassLoader 中)写死了双亲委派流程:收到类加载请求后,不立即查找本地资源,而是先调用 parent.loadClass();父加载器返回 null 或抛出 ClassNotFoundException,才轮到自己调用 findClass() 去查。这个“向上委托 + 向下 fallback”的硬编码逻辑,就是双亲委派模型的全部骨架。
它不是靠继承关系或接口约束实现的,而是靠每个子类加载器在构造时显式持有父加载器引用,并在 loadClass 里强制调用它——哪怕你自定义一个 MyClassLoader 继承 ClassLoader,只要没重写 loadClass,就自动遵守这套规则。
为什么自定义 java.lang.String 不会生效
当你写一个 public class String extends Object { ... } 并试图用 MyClassLoader 加载它时,loadClass("java.lang.String") 会一路委托到 BootstrapClassLoader;后者只认 $JAVA_HOME/jre/lib/rt.jar 里的 java/lang/String.class,并成功返回对应 Class 对象;后续所有加载器都不会再尝试加载——你的类根本不会被 findClass 触达。
常见错误现象包括:
- 运行时报
NoClassDefFoundError: java/lang/String(其实是启动失败,因 JVM 检测到类型不一致) - 编译通过但运行时提示 “找不到 main 方法”,因为 JVM 找到的是 rt.jar 中的
String,而它没有main入口 - 直接抛
SecurityException:JVM 在初始化阶段会对java.*包名做白名单校验,连加载机会都不给
破坏双亲委派的典型场景与风险
有些框架(如 Tomcat、OSGi)会主动绕过默认 loadClass 流程,改为“先自己查,查不到再委托”。这种破坏不是 bug,而是为了解决实际问题,比如 Web 应用间类隔离、热部署等。
但随意破坏会触发严重后果:
- 若应用类加载器优先加载了
java.util.ArrayList的篡改版本,可能导致BootstrapClassLoader加载的java.lang.ClassLoader在运行时调用它,引发LinkageError(类链接冲突) - 不同加载器加载的同名类,即使字节码完全一样,在 JVM 中也被视为不同类,无法强转、无法共用静态变量
-
System.setProperty("java.security.manager", "xxx")等安全机制依赖双亲委派保证核心类可信,破坏后沙箱形同虚设
验证双亲委派是否生效的简单方式
不必翻源码或调试 JVM,只需观察类的 ClassLoader 引用链:
System.out.println(String.class.getClassLoader()); // null(Bootstrap 不是 Java 对象) System.out.println(MyAppClass.class.getClassLoader()); // AppClassLoader 实例 System.out.println(MyAppClass.class.getClassLoader().getParent()); // ExtClassLoader 实例 System.out.println(MyAppClass.class.getClassLoader().getParent().getParent()); // null(Ext 的 parent 是 Bootstrap)
关键点在于:java.lang.* 下所有类的 getClassLoader() 都返回 null,这是 JVM 硬编码的标识;而任何用户类,只要没被自定义加载器劫持,其加载器链最终都会指向 null —— 这条链本身,就是双亲委派在内存中的投影。
真正容易被忽略的,是那个看似无害的 findClass:它只负责“找字节码”,不负责“解析父子关系”;一旦你重写了 loadClass 却忘了调用父类逻辑,或者把 parent 设为 null,整个安全边界就从根上断了。


















