JAVA双亲委派加载机制

双亲委派(Parent Delegation)是 Java 类加载机制中的一种核心设计原则,用于确保类的唯一性、安全性和层次化加载。它的核心思想是:当一个类加载器需要加载某个类时,不会立即自己尝试加载,而是先将请求委派给父类加载器处理。这种逐级向上委派的机制形成了类加载的层次结构。


双亲委派的工作流程

  1. 自底向上委派
    当子类加载器收到加载类的请求时:

    • 先检查该类是否已被加载过。

    • 若未加载,优先委派给父类加载器处理(而非自己直接加载)。

    • 父类加载器会重复此过程,直到请求传递到顶层的 启动类加载器(Bootstrap ClassLoader)

  2. 自顶向下尝试加载

    • 如果父类加载器能完成加载,直接返回该类。

    • 如果父类加载器无法加载(例如父类加载器的搜索范围内没有该类),子类加载器才会尝试自己加载。


类加载器的层次结构

Java 默认类加载器按层级从高到低分为:

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

    • 由 C++ 实现,负责加载 JRE/lib 下的核心类库(如 rt.jar)。

  2. 扩展类加载器(Extension ClassLoader)

    • 由 Java 实现,负责加载 JRE/lib/ext 目录下的类。

  3. 应用程序类加载器(Application ClassLoader)

    • 加载用户类路径(classpath)下的类。

  4. 自定义类加载器(Custom ClassLoader)

    • 用户可自定义类加载器,继承 ClassLoader 类。


双亲委派的优点

  1. 避免重复加载
    父类加载器加载过的类,子类加载器不会重复加载,确保类的唯一性。

    • 例如:java.lang.Object 始终由启动类加载器加载,全局唯一。

  2. 安全性
    防止用户自定义的类冒充核心类(如伪造 java.lang.String),因为父类加载器会优先加载核心类库。

  3. 职责分离
    不同层级的类加载器负责不同范围的类加载,形成清晰的边界。


双亲委派的例外情况

某些场景会打破双亲委派机制:

  1. SPI(Service Provider Interface)

    • 核心类(如 JDBC)需调用第三方实现(如 MySQL 驱动)。

    • 通过 线程上下文类加载器(Thread Context ClassLoader) 逆向委派子类加载器加载。

  2. 热部署/热替换

    • 如 Tomcat 为每个 Web 应用提供独立的类加载器,优先加载自身目录的类,未找到再委派父类加载器。

  3. 模块化系统(如 OSGi)

    • 允许类加载器网状委派,实现动态模块化加载。

代码示例

类加载器的 loadClass 方法默认实现双亲委派逻辑:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        // 1. 检查是否已加载
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            try {
                // 2. 委派父类加载器
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    // 父类加载器为 Bootstrap ClassLoader
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // 父类加载失败,不抛异常
            }

            if (c == null) {
                // 3. 父类无法加载时,自己尝试加载
                c = findClass(name);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

总结

双亲委派是 Java 类加载的核心机制,通过逐级向上委派、向下尝试加载,保障了类的一致性和安全性。尽管某些场景需要打破这一机制(如 SPI、热部署),但其设计思想仍是理解 Java 类加载体系的基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值