JVM 类加载:双亲委派机制

双亲委派机制:一句话说清楚它是啥

一句话总结

双亲委派就是------类加载时,先让父类加载器去加载,父类加载不了,才由自己加载

目的是保证核心类由高层加载器统一加载,防止被替换,确保安全和唯一。


一、什么是"双亲委派"?

"双亲"其实是翻译问题,它不是指"父母双方",而是"父辈"的意思。更准确的说法是"父类委派"。

它的规则只有一条:

当一个类加载器收到加载类的请求时,它不急着自己加载,而是先把请求交给父类加载器去处理。只有父类加载器明确表示"我加载不了",自己才动手。

这个"父",不是 Java 中的继承关系,而是类加载器之间的委托关系


二、类加载器有哪些?

Java 中的类加载器分为四层,从上到下是:

类加载器 实现方式 负责加载
Bootstrap ClassLoader JVM 用 C++ 实现 rt.jar 等核心类库(如 java.lang.*
Extension ClassLoader Java 实现 jre/lib/ext 目录下的扩展类
Application ClassLoader Java 实现 classpath 下的用户类(你的代码)
自定义 ClassLoader 继承 ClassLoader 特殊需求,如网络加载、热部署

它们之间形成一条链:

复制代码
自定义 → Application → Extension → Bootstrap

加载请求从下往上层层委派,一旦某一层能加载,就直接返回,不再往下。


三、为什么要有双亲委派?

1. 防止核心类被篡改

试想:如果你写了一个 java.lang.String,放在项目里。

如果没有双亲委派,Application ClassLoader 可能会加载你写的这个"假" String,那整个系统就乱了。

但因为有双亲委派,加载请求会先被委派到 Bootstrap ClassLoader,它从 rt.jar 中加载了真正的 String,你的类根本不会被加载。

✅ 所以,你永远无法替换核心类

2. 避免类重复加载

同一个类,比如 java.util.ArrayList,如果被多个类加载器各自加载,就会出现多个 Class 对象。

这会导致:

  • instanceof 判断失败;
  • 类型转换异常;
  • 静态变量不共享。

双亲委派确保这类核心类只被最顶层的加载器加载一次,保证唯一性。

3. 安全

核心类库由最可信的 Bootstrap ClassLoader 加载,它不走 Java 层代码,不受用户控制。

这种自顶向下的信任链,让 JVM 能抵御恶意代码的攻击。


四、双亲委派是怎么实现的?

核心就在 ClassLoader.loadClass() 方法里。

JDK 8 中的关键逻辑如下:

java 复制代码
protected Class<?> loadClass(String name, boolean resolve) {
    // 1. 先查自己是否已加载
    Class<?> c = findLoadedClass(name);
    if (c == null) {
        try {
            // 2. 有父类,先让父类加载
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                // 父为 null,表示使用 Bootstrap
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // 父类加载失败,继续
        }
        // 3. 父类没加载成功,自己加载
        if (c == null) {
            c = findClass(name);
        }
    }
    return c;
}

这个方法定义了标准流程

查缓存 → 委派父类 → 自己加载。

除非你重写它,否则所有类加载器都必须遵守。


五、双亲委派能打破吗?

能。通过重写 loadClass 方法,可以改成"先自己加载,再委派父类",这就是打破双亲委派

常见场景:

  • Tomcat:每个 Web 应用用独立类加载器,避免应用之间类冲突;
  • OSGi:模块化框架,支持不同模块用不同版本的同一个库;
  • 热部署:重新加载类而不重启 JVM。

代价:

  • 类唯一性没了;
  • 需要自己处理类隔离、冲突、卸载等问题;
  • 复杂度高,一般只在框架层面使用。

相关推荐
Java水解2 分钟前
【Spring Boot】Spring 魔法世界:Bean 作用域与生命周期的奇妙之旅
spring boot·后端
西岭千秋雪_3 分钟前
Zookeeper监听机制
java·linux·服务器·spring·zookeeper
毕设源码-林学长7 分钟前
计算机毕业设计java和Vue的安全教育科普平台设计与实现 安全知识普及与教育平台 安全教育信息化管理平台
java·开发语言·课程设计
ruleslol11 分钟前
java-接口适配器模式 & jsk8 接口默认实现
java·适配器模式
JohnYan12 分钟前
Bun技术评估 - 26 Abort
javascript·后端·bun
逛逛GitHub15 分钟前
国产首个开源 AI 原生后端平台,这次是真起飞了。
后端·github
Python私教16 分钟前
Rust 编程语言基础知识全面介绍
开发语言·后端·rust
鬼火儿16 分钟前
网卡驱动架构以及源码分析
java·后端
老华带你飞25 分钟前
房屋租赁|房屋出租|房屋租赁系统|基于Springboot的房屋租赁系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·vue·论文·毕设·房屋租赁系统
TDengine (老段)28 分钟前
TDengine 数学函数 ASCII 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据