双亲委派模型是什么,为什么要使用双亲委派模型

news2024/11/15 11:16:03

双亲委派模型是什么,为什么要使用双亲委派模型

在Java中,类加载器(ClassLoader)是负责将类文件加载到JVM中的关键组件。为了确保类加载过程的安全性和稳定性,Java引入了一种叫做双亲委派模型(Parent Delegation Model)的机制。这篇文章将介绍什么是双亲委派模型,以及为什么要使用这种模型。

什么是双亲委派模型

双亲委派模型是一种类加载机制,它要求类加载器在加载一个类时,首先把这个请求委托给它的父类加载器去处理。只有当父类加载器无法完成这个请求时,子类加载器才会尝试加载这个类。这个过程可以递归进行,从最顶层的类加载器一直到最底层的类加载器。

Java中的类加载器可以分为以下几种:

  1. Bootstrap ClassLoader:引导类加载器,它是Java虚拟机自带的类加载器,负责加载Java核心类库,如rt.jar
  2. Extension ClassLoader:扩展类加载器,负责加载JAVA_HOME/lib/ext目录中的类。
  3. Application ClassLoader:应用程序类加载器,负责加载应用程序类路径(classpath)上的类。

这三种类加载器按照上述顺序形成了一个树状的双亲委派关系。

为什么要使用双亲委派模型

  1. 安全性:双亲委派模型确保了核心类库的安全性。通过这种模型,Java核心类库只能由引导类加载器加载,防止应用程序中的类覆盖或篡改核心类库。例如,java.lang.Object类总是由引导类加载器加载,这样可以避免安全风险。

  2. 避免类的重复加载:在双亲委派模型中,每个类加载器都有一个独立的命名空间。当一个类被加载后,它的类加载器会缓存这个类的字节码信息。在需要再次加载这个类时,类加载器会先检查缓存,从而避免重复加载同一个类,节省了资源并提高了性能。

  3. 逻辑清晰:双亲委派模型使类加载过程更加清晰和易于管理。类加载器之间有明确的职责分工,父类加载器处理基础类,子类加载器处理应用类。这样,整个类加载过程变得层次分明,易于理解和调试。

例子:双亲委派模型的工作流程

假设我们有一个自定义的类加载器MyClassLoader,它想要加载一个类com.example.MyClass,双亲委派模型的工作流程如下:

  1. 检查缓存MyClassLoader首先检查是否已经加载过com.example.MyClass
  2. 委派给父类加载器:如果未加载过,MyClassLoader将把这个请求委派给父类加载器,通常是应用程序类加载器。
  3. 应用程序类加载器处理请求:应用程序类加载器会再次检查它是否已经加载过com.example.MyClass,如果没有,它会继续把请求委派给扩展类加载器。
  4. 扩展类加载器处理请求:扩展类加载器同样会检查是否已经加载过该类,如果没有,它会继续把请求委派给引导类加载器。
  5. 引导类加载器处理请求:引导类加载器会检查是否在核心类库中找到该类。如果找不到,引导类加载器会返回一个ClassNotFoundException
  6. 自定义类加载器加载类:如果父类加载器都无法加载该类,自定义的MyClassLoader才会尝试自己加载com.example.MyClass

自定义类加载器如何实现双亲委派

自定义类加载器实现双亲委派模型的核心在于重写findClass方法,并在该方法中调用父类加载器加载类。具体步骤如下:

  1. 继承ClassLoader:自定义类加载器需要继承java.lang.ClassLoader类。

  2. 重写findClass方法:在findClass方法中,首先尝试使用父类加载器加载类,如果父类加载器无法加载,则再使用自定义的加载逻辑。

以下是一个实现双亲委派模型的自定义类加载器的示例:

public class MyClassLoader extends ClassLoader {

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 首先,尝试使用父类加载器进行加载
        try {
            return getParent().loadClass(name);
        } catch (ClassNotFoundException e) {
            // 如果父类加载器无法加载该类,则继续尝试自定义加载
        }

        // 自定义加载逻辑,例如从文件系统中加载类文件
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        }

        return defineClass(name, classData, 0, classData.length);
    }

    private byte[] getClassData(String className) {
        // 实现自定义类加载逻辑,例如从文件系统中读取类文件
        String path = className.replace('.', '/') + ".class";
        try (InputStream input = new FileInputStream(path);
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
            return output.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

在上述代码中,findClass方法首先尝试通过父类加载器加载类(即实现双亲委派模型),如果父类加载器无法加载,则使用getClassData方法通过自定义逻辑加载类。

自定义类加载器如果不实现双亲委派模型会怎样?

如果自定义类加载器不实现双亲委派模型,可能会带来以下几个问题:

  1. 类的重复加载
    不实现双亲委派模型会导致同一个类可能被多个类加载器重复加载。每个类加载器加载的类在JVM中被视为不同的类,即使它们来自相同的字节码文件。这可能导致ClassCastException等问题。

  2. 安全性问题
    核心类库可能会被恶意替换。例如,如果自定义类加载器可以加载java.lang.Object类,那么程序的核心安全性将受到威胁。

  3. 稳定性问题
    Java平台的稳定性依赖于类加载顺序和唯一性。不实现双亲委派模型可能导致核心类库的加载顺序混乱,影响程序的正常运行。

  4. 与现有库的兼容性问题
    许多现有的Java库和框架依赖于双亲委派模型来确保类的加载顺序和一致性。如果不实现双亲委派模型,这些库和框架可能无法正常工作。

如果想自定义类加载器,就需要继承ClassLoader,并重写findClass,如果想不遵循双亲委派的类加载顺序,还需要重写loadClass。如下是一个自定义的类加载器,并重写了loadClass破坏双亲委派:

public class MyClassLoader extends ClassLoader {

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 直接使用自定义加载逻辑,不调用父类加载器
        return findClass(name);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 自定义加载逻辑,例如从文件系统中加载类文件
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        return defineClass(name, classData, 0, classData.length);
    }

    private byte[] getClassData(String className) {
        // 实现自定义类加载逻辑,例如从文件系统中读取类文件
        String path = className.replace('.', '/') + ".class";
        try (InputStream input = new FileInputStream(path);
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
            return output.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

在上述代码中,loadClass 方法没有调用父类加载器,而是直接调用自定义的 findClass 方法加载类,这样就不遵循双亲委派模型。

综上所述,为了保证 Java 应用的安全性、稳定性以及与现有库的兼容性,推荐在自定义类加载器中实现双亲委派模型。

结论

双亲委派模型在Java的类加载机制中扮演着重要角色。它通过安全性、避免类的重复加载和逻辑清晰等优势,确保了Java程序的稳定性和可靠性。理解和掌握双亲委派模型对于开发和调试Java应用程序是非常重要的。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1814412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

联合数据库,申请出战!新指标“超级老人”揭示老年健康新视角,仅用logistic分析发文二区...

说到老年数据库&#xff0c;大家最熟悉的肯定是Charls&#xff0c;实际上类似免费好用的老年数据库还有很多&#xff0c;在没有思路的时候我们不妨看一下其他数据库的文章&#xff0c;说不定能找到新的思路或者切入点。 今天介绍的这篇文章就提出来一个新的概念-“超级老人”&a…

中国(广州)国际物流装备展圆满收官,铨顺宏邀您6月上海档案展

2024年5月29日-31日&#xff0c;为期三天的第十五届中国(广州)国际物流装备与技术展览会圆满收官。此次展会汇聚了物流装备与技术领域的众多行业精英和领先企业&#xff0c;展示了最新的技术和产品。铨顺宏科技作为物联网设备和技术服务领提供商&#xff0c;携RFID、BLE、UWB和…

按位拆分+前缀和,CF 1879D - Sum of XOR Functions

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1879D - Sum of XOR Functions 二、解题报告 1、思路分析 朴素暴力O(N^2)&#xff0c;考虑优化 由于要求的是异或值乘长度&#xff0c;那么我们可以按位考虑每一位异或值的贡献 我们枚举每一位 每次遍历…

TMCM-BB1是单轴板驱动器

TMCM-BB4 简介 TMCM-BB1和TMCM-BB4是Trinamic插槽式模块的基板。TMCM-BB1是单轴板&#xff0c;提供对一个MCU模块和一个驱动器模块的访问。TMCM-BB4是一个4轴板&#xff0c;提供对41模块插槽的访问。TMCM-0930模块采用单36针PCI插座&#xff0c;整个系统采用主MCU&#xff08;…

[Shell编程学习路线]--shell中重定向和管道符(详细介绍)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f6e0;️Shell编程专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月12日10点50分 &#x1f004;️文章质量&#xff1a;93分 ——前言—— 在Shell编程中&#xff0c;重定向和管道符是两个…

超声波清洗机哪家好?四大人气爆单超声波清洗机汇总安利

在日常生活中&#xff0c;我们每天都在与灰尘和污渍作斗争&#xff0c;尤其是对于那些细小、精密的物品&#xff0c;如眼镜。眼镜不仅是视力矫正的工具&#xff0c;更是我们个人形象的一部分。一副干净、明亮的眼镜可以让我们的视线更加清晰。因为保持眼镜的清洁是一件很重要的…

接上篇---dbeaver如何导入csv文件(科学计数法)以及导出csv(科学计数法如何处理)

前提由于我用的是社区版本的&#xff0c;不支持excel&#xff0c;只支持csv导入导出 1.导入时候遇见科学计数法的解决方案&#xff1b; 由于我处理的是一些合同编码&#xff0c;虽然excel我给它设置成了文本类型&#xff0c;但是另存为csv的时候还是会变成科学计数法&#xf…

【关注】科大睿智祝贺企业通过ITSS公示名单

近日&#xff0c;根据信息技术服务标准符合性评估相关规定&#xff0c;现对以下单位进行公示&#xff0c;公示期5个工作日。公示期内如有异议&#xff0c;请提供持有异议的正式书面文件&#xff0c;包括持有异议的原因及证据、单位或个人真实名称及有效联系方式。小编祝贺多家服…

音视频封装的总接

1、封装涉及的基本概念 2、音视频封装基础3、封装总结 4、PS/TS码流封装层次图

c# 绘制正玄函数 控制台绘制

1.概要 2.代码 using System;class Program {static void Main(){const int width 80; // 控制台宽度 const int height 20; // 正弦波的高度范围 const double period 10.0; // 正弦波的周期 const double amplitude 5.0; // 正弦波的振幅 for (int x 0; x < wi…

衡量网络性能的指标

带宽 测速&#xff0c;下载速度一般是MB&#xff0c;运营商用的是b&#xff0c;之间有差别&#xff0c;100M带宽就是100M b 100个人访问同一个服务器&#xff0c;那么这个服务器的并发连接数就是100&#xff0c;有上限&#xff0c;受到性能的限制&#xff0c;当前面连接好多了…

JS :深拷贝解析与实现(附structuredClone语法测试)

浅拷贝简介 深拷贝是创建一个新对象&#xff0c;这个新对象包含原对象所有属性的全新拷贝&#xff0c;无论是基本数据类型还是引用类型的数据都会被完全复制一份&#xff0c;新旧对象间不存在任何关联&#xff0c;彼此独立。 前言 OK&#xff0c;最近又又又在学习JS的过程中…

【STM32之FreeRTOS(三)】任务的调度与状态

【STM32之FreeRTOS(三)】任务的调度与状态 文章目录 【STM32之FreeRTOS(三)】任务的调度与状态一、什么是任务调度&#xff1f;二、FreeRTOS的任务调度规则1.抢占式调度运行过程2.时间片调度运行过程 三、任务的状态四、任务综合小实验1.实验需求2.CubeMX配置2.1 配置KEY1,KEY2…

学生护眼台灯哪个品牌好?一文教会你如何挑选学生护眼台灯

台灯作为我们日常生活中重要的桌面照明工具&#xff0c;对于办公族的工作和学生的学习都扮演着关键角色。长期使用质量不佳的台灯可能会对我们的视力健康造成不利影响&#xff0c;尤其是对于眼睛尚在发育阶段的学生来说&#xff0c;这种影响更为显著。因此&#xff0c;在选择台…

表字段如何设计,如何打标签,如何进行维度分组,关于优先级排序如何处理(大数据开发)

今天分享一篇&#xff0c;热腾腾的实战&#xff0c;关于在数据开发中&#xff0c;表字段如何设计&#xff0c;如何打标签&#xff0c;如何进行维度分组&#xff0c;关于优先级排序如何处理&#xff1f;&#xff1f;&#xff1f; 1&#xff0c;表字段如何设计 首先&#xff0c…

RPG Maker MZ中被你忽略的干货操作——事件页优先级

文章目录 事件页优先级问题结论问题1答案 事件页优先级问题 结论 事件页2的优先级是大于事件页1的 问题1 事件页1没有条件、自动执行生成图片&#xff0c;效果如下 事件页2&#xff0c;没有条件&#xff0c;自动执行&#xff0c;效果如下 答案 只会执行事件页2&#…

数据库索引推荐大PK,DBdoctor和资深DBA的终极较量

前言 在上一篇文章《端午特别篇&#xff1a;你真的了解数据库索引吗&#xff1f;》中&#xff0c;纪宽针对一个业务SQL推荐索引优化问题提出了疑问。他发现DBdoctor推荐的索引组合&#xff08;status, purchase_date,device_name, device_id&#xff09;似乎与他作为DBA凭借多…

vue element-ui 下拉框 以及 input 限制输入,小数点后保留两位 界面设计案例 和 例子:支持mp4和m3u8视频播放

vue input 限制输入&#xff0c;小数点后保留两位 以及 图片垂直居中显示 和 分享 git 小技巧-CSDN博客文章浏览阅读430次&#xff0c;点赞5次&#xff0c;收藏4次。error:Your local changes to the following files would be overwritten by merge:_error: your local change…

传神社区|数据集合集第3期|中文NLP数据集合集

自从ChatGPT等大型语言模型&#xff08;Large Language Model, LLM&#xff09;出现以来&#xff0c;其类通用人工智能&#xff08;AGI&#xff09;能力引发了自然语言处理&#xff08;NLP&#xff09;领域的新一轮研究和应用浪潮。尤其是ChatGLM、LLaMA等普通开发者都能运行的…

计算机SCI期刊,中科院3区,IF=3.4,难度不大,无预警风险

一、期刊名称 Automated Software Engineering 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;3.4 中科院分区&#xff1a;3区 三、期刊征稿范围 自动化软件工程是一份档案&#xff0c;同行评审的期刊&#xff0c;发表研…