【无标题】

下面用最直白、面试可直接背的方式讲清楚 双亲委派机制(Parent Delegation Model)。


一、一句话定义

类加载器收到加载请求 → 先交给父加载器 → 父加载不了 → 自己再加载。

目的:保证核心类安全、全局唯一、防止篡改。

"双亲"不是两个父类,是层级链上的父加载器(翻译问题)。


二、三层加载器(JDK8)

从上到下:

  1. Bootstrap ClassLoader(启动类加载器)

    • C++写的,JVM内置
    • 加载:rt.jar 核心类(java.lang.String、Object...)
    • 路径:$JAVA_HOME/lib
  2. Extension ClassLoader(扩展类加载器)

    • Java写的
    • 加载:lib/ext 或 java.ext.dirs 的扩展类
  3. Application ClassLoader(应用/系统类加载器)

    • Java写的
    • 加载:项目 classpath 下的类、第三方jar
    • 日常代码几乎都是它加载

父子关系是 组合(parent 字段),不是 Java 继承。


三、执行流程(必背)

以加载 com.example.MyClass 为例:

  1. AppClassLoader 收到请求
  2. 检查:是否已加载过? → 是,直接返回
  3. 没加载 → 委派给父:ExtClassLoader
  4. ExtClassLoader 同样:有缓存返回,没缓存 → 委派给 Bootstrap
  5. Bootstrap:
    • 在 rt.jar 找 → 找不到(因为是你自己的类)
    • 返回"加载失败"
  6. 回到 ExtClassLoader:自己路径也找不到 → 失败
  7. 回到 AppClassLoader:自己调用 findClass 加载 → 成功

总结:自下而上委派,自上而下加载;父优先,子兜底。


四、核心作用(面试高频)

  1. 安全:防止核心类被篡改

    • 你自己写一个 java.lang.String,不会被加载
    • 因为 Bootstrap 优先加载 rt.jar 里的正版 String
  2. 唯一:一个类在 JVM 中只一份

    • 全链路委派,保证不会重复加载
  3. 隔离:不同加载器的类互相隔离

    • 例如:AppClassLoader 加载的 A 类 ≠ 自定义加载器加载的 A 类

五、什么时候打破双亲委派?

默认是双亲委派,但有些场景必须打破:

  1. Tomcat:

    • 每个 Web 应用有自己的类加载器
    • 先加载自己 war 包里的类,再委派父加载器
    • 目的:Web 应用之间类隔离、热部署
  2. JDBC 驱动加载:

    • Bootstrap 加载 java.sql.Driver(接口)
    • 实现类在应用 jar 里,需要反向委派
  3. 热部署、OSGi、模块化框架

打破方式:重写 ClassLoader 的 loadClass 方法,不先委派父加载器。


六、源码核心(简化版)

java 复制代码
protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException {
    // 1. 检查是否已加载
    Class<?> c = findLoadedClass(name);
    if (c == null) {
        try {
            if (parent != null) {
                // 2. 委派父加载器
                c = parent.loadClass(name, false);
            } else {
                // 3. 父为null → 调用Bootstrap
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // 父加载失败
        }
        if (c == null) {
            // 4. 自己加载
            c = findClass(name);
        }
    }
    if (resolve) resolveClass(c);
    return c;
}

关键:loadClass 默认先委派;findClass 由子类重写实现自己的加载逻辑。


七、面试极简背诵版

  • 定义:加载类时先委派父加载器,父不能加载才自己加载。
  • 三层:Bootstrap → Ext → App。
  • 流程:自下而上委派,自上而下加载。
  • 作用:安全防篡改、全局唯一、类隔离。
  • 打破:重写 loadClass,如 Tomcat、JDBC。

相关推荐
蜗牛互联网15 分钟前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
禾小西43 分钟前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨1 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
小卡车5551 小时前
java反射、自定义注解的应用(自定义分页)
java
BLUcoding2 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom
yuniko-n2 小时前
【JUC】Lock 和 synchronzied 锁
java
西柚小萌新2 小时前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库
北极有牛2 小时前
cpp学习笔记--常量指针
java·开发语言·算法
java资料站2 小时前
二、Spring AI Alibaba · ChatModel
java·windows·spring
十年Java程序媛3 小时前
Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型
java·spring boot·后端