【无标题】

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

相关推荐
yoyo_zzm6 小时前
四大编程技术对比:PHP、Java、Python与HTML
java·python·php
海兰6 小时前
【第54篇】Graph + Langfuse 可观测性实战
java·人工智能·spring boot·spring ai
笨拙的老猴子6 小时前
JDK8 / JDK11 / JDK17 / JDK21 核心新特性对比,简单总结
java·jdk
江湖中的阿龙7 小时前
【无标题】
java·开发语言
JavaEdge在掘金7 小时前
06-LangChain Tool 加载与使用指南:预制工具、SerpAPI、edge-tts、GraphQL
java
NettyBoy7 小时前
生产 YoungGC 导致的系统化卡顿
java·jvm
聚美智数7 小时前
食物热量搜索与详情双接口接入实战,轻量化生活服务 API 落地
java·开发语言·生活