当前位置: 首页 > article >正文

【JAVA基础】双亲委派

双亲委派可以简单理解为, 当收到加载请求时, 会依次向上加载 ; 只有当父类加载器无法完成加载请求时,子类加载器才会尝试自己去加载。

工作原理

  • 类加载请求传递:当应用程序需要加载一个类时,比如通过ClassLoader.loadClass()方法,首先会由应用程序类加载器(通常是系统类加载器)接收到这个请求。然后,它会将这个请求委托给它的父类加载器 —— 扩展类加载器。扩展类加载器又会将请求进一步委托给启动类加载器。
  • 类加载尝试顺序:启动类加载器首先尝试加载类,如果它能找到并加载这个类,那么就完成了类加载过程。如果启动类加载器无法加载,它会将任务返回给扩展类加载器,让扩展类加载器尝试加载。如果扩展类加载器也无法加载,就再将任务返回给应用程序类加载器,由应用程序类加载器尝试加载。如果应用程序类加载器也无法加载,才会抛出ClassNotFoundException异常

作用

  • 避免类的重复加载:通过双亲委派机制,当一个类已经被某个类加载器加载过了,那么其他类加载器就不会再次加载它,保证了类在整个 Java 虚拟机中只有一份实例,节省了内存空间,也避免了因类的重复加载而可能导致的各种问题。
  • 保证类的安全性:它确保了 Java 核心类库的安全性。例如,java.lang.Object类是由启动类加载器加载的,其他类加载器在加载类时,如果需要加载java.lang.Object类,都会委托给启动类加载器,这样就保证了所有的类都使用的是 Java 核心类库中的Object类,而不是被恶意篡改过的版本,防止了核心类被非法替换或篡改。
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 首先检查该类是否已经被加载过
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            try {
                // 尝试使用父类加载器加载
                if (getParent()!= null) {
                    c = getParent().loadClass(name);
                } else {
                    // 如果父类加载器为null,说明已经到了启动类加载器,使用系统类加载器加载
                    c = ClassLoader.getSystemClassLoader().loadClass(name);
                }
            } catch (ClassNotFoundException e) {
                // 如果父类加载器无法加载,则尝试自己加载
                c = findClass(name);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 自定义类加载逻辑,从文件或网络等获取类的字节码
        // 这里只是简单示例,实际应用中需要根据具体情况实现
        String className = name.substring(name.lastIndexOf('.') + 1) + ".class";
        InputStream is = getClass().getResourceAsStream(className);
        if (is == null) {
            throw new ClassNotFoundException(name);
        }
        try {
            byte[] b = new byte[is.available()];
            is.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            throw new ClassNotFoundException(name);
        }
    }
}

MyClassLoader类继承自ClassLoader类,重写了loadClass方法来实现双亲委派机制。首先会检查类是否已经被加载过,如果没有,则先尝试使用父类加载器加载,如果父类加载器无法加载,再尝试自己加载。findClass方法用于自定义类的加载逻辑,这里只是简单地从当前类所在的路径下读取类的字节码


http://www.kler.cn/a/528297.html

相关文章:

  • 自制虚拟机(C/C++)(二、分析引导扇区,虚拟机读二进制文件img软盘)
  • Python3 【装饰器】项目实战:5个新颖的学习案例
  • pytorch基于FastText实现词嵌入
  • 音视频多媒体编解码器基础-codec
  • electron 应用开发实践
  • 事务03之MVCC机制
  • 携程Android开发面试题及参考答案
  • docker直接运行arm下的docker
  • 冯·诺依曼体系结构
  • 基于Python的人工智能患者风险评估预测模型构建与应用研究(上)
  • Vue- 组件通信2
  • Recommender Systems with Large Models
  • deepseek 模型 V3 和 R1 的区别
  • UE求职Demo开发日志#18 数据表获取物品信息,添加背包模块
  • 数据结构【链栈】
  • 攻防世界_Web_php_unserialize(绕过php反序列/绕过wakeup函数/代码审计)
  • 移动互联网用户行为习惯哪些变化,对小程序的发展有哪些积极影响
  • 群晖Alist套件无法挂载到群晖webdav,报错【连接被服务器拒绝】
  • 【oracle】分组求最新日期的数据
  • JavaScript系列(51)--解释器实现详解
  • 日志2025.2.1
  • 断裂力学课程报告
  • 软件工程经济学-日常作业+大作业
  • java每日精进1.31(SpringSecurity)
  • 云中漫步:精工细作铸就免费公益刷步平台
  • php的使用及storm环境部署