【无标题】

下面用最直白、面试可直接背的方式讲清楚 双亲委派机制(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。

相关推荐
摇滚侠17 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown17 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
折哥的程序人生 · 物流技术专研18 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则
装不满的克莱因瓶18 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
程序员小羊!18 小时前
06Java 异常机制与常用类
java
weixin_5231853218 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
宸津-代码粉碎机19 小时前
Spring AI企业级实战|从RAG优化到Agent多工具调度
java·大数据·人工智能·后端·python·spring
噢,我明白了19 小时前
QueryWrapper的使用
java
Chase_______19 小时前
【Java基础 | 15】集合框架(中):Set、HashSet、TreeSet 与哈希表
java·windows·散列表
摇滚侠19 小时前
Maven 入门+高深 微服务案例 122-125
java·微服务·maven