【无标题】

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


一、一句话定义

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

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

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


二、三层加载器(JDK8)

从上到下:

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

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

    • Java写的
    • 加载:lib/extjava.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。

相关推荐
万亿少女的梦1688 分钟前
基于Spring Boot、Java与MySQL的网络订餐系统设计与实现
java·spring boot·mysql·系统设计·网络订餐
咩咩啃树皮8 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚9 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白10 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司11 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地12 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415912 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风15 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
z1234567898615 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112316 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python