java中双亲委派详解

news2025/2/22 6:10:59

什么是双亲委派机制?

双亲委派机制(Parent Delegation Model)是Java类加载器(ClassLoader)加载类时的一种策略。它的核心思想是:当一个类加载器收到加载类的请求时,不会立即自己加载,而是先将请求委派给父类加载器处理。只有当父类加载器无法完成加载时,子类加载器才会尝试自己加载。

1. 双亲委派机制的核心思想

双亲委派机制的核心思想可以用一句话概括:“先让父类加载器尝试加载类,父类加载器无法完成时,才由子类加载器自己加载。”

这种机制是一种层次化的类加载模型,每个类加载器都有一个父类加载器(除了顶层的Bootstrap ClassLoader)。类加载器在加载类时,会按照以下步骤进行:

  1. 委派:将加载请求委派给父类加载器。

  2. 检查:父类加载器检查是否已经加载过该类。

  3. 加载:如果父类加载器无法加载,子类加载器才会尝试加载。


2. 类加载器的层次结构

Java中的类加载器是一个树形结构,分为以下几层:

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

  • 职责:加载JVM核心类库(如java.lang.*java.util.*等),这些类库位于JAVA_HOME/lib目录下。

  • 特点

    • 由C++实现,是JVM的一部分。

    • 没有父类加载器(它是类加载器树的根节点)。

    • 无法在Java代码中直接获取(返回null)。

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

  • 职责:加载JAVA_HOME/lib/ext目录下的类库,或者由java.ext.dirs系统属性指定的目录。

  • 特点

    • 由Java实现,对应的类是sun.misc.Launcher$ExtClassLoader

    • 父类加载器是Bootstrap ClassLoader。

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

  • 职责:加载用户类路径(ClassPath)上的类库。

  • 特点

    • 由Java实现,对应的类是sun.misc.Launcher$AppClassLoader

    • 父类加载器是Extension ClassLoader。

    • 是默认的类加载器,负责加载用户编写的类。

(4)自定义类加载器

  • 职责:用户可以通过继承ClassLoader类,实现自定义的类加载逻辑。

  • 特点

    • 父类加载器通常是Application ClassLoader。

    • 可以打破双亲委派机制,实现特定的类加载需求。


3. 双亲委派的工作流程

当一个类加载器收到加载类的请求时,会按照以下步骤执行:

  1. 检查是否已加载

    • 类加载器首先检查自己是否已经加载过该类。如果已经加载,直接返回该类。

  2. 委派给父类加载器

    • 如果未加载,将加载请求委派给父类加载器。

    • 父类加载器重复同样的过程,继续向上委派,直到Bootstrap ClassLoader。

  3. 父类加载器尝试加载

    • 如果父类加载器能够加载该类,加载过程结束。

    • 如果父类加载器无法加载,子类加载器才会尝试自己加载。

  4. 子类加载器尝试加载

    • 如果子类加载器也无法加载,抛出ClassNotFoundException


4. 双亲委派的代码实现

双亲委派机制的实现主要在ClassLoader类的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 {
                    // 如果父类加载器为null,说明是Bootstrap ClassLoader
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // 父类加载器无法加载,忽略异常
            }

            // 3. 父类加载器无法加载时,自己尝试加载
            if (c == null) {
                c = findClass(name);
            }
        }
        // 4. 如果需要解析,解析该类
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

关键点:

  • findLoadedClass:检查是否已经加载过该类。

  • parent.loadClass:委派给父类加载器。

  • findClass:父类加载器无法加载时,自己尝试加载。


5. 双亲委派的优点

(1)避免重复加载

  • 由于类加载器会先委派给父类加载器,确保每个类只被加载一次,避免重复加载。

(2)安全性

  • 防止用户自定义的类替换核心类库中的类(如java.lang.String),确保核心类库的安全性。

(3)一致性

  • 保证同一个类在不同类加载器环境下的一致性。


6. 双亲委派的缺点

(1)灵活性不足

  • 在某些场景下,双亲委派机制可能不够灵活。例如:

    • 需要加载不同版本的类库。

    • 需要隔离不同模块的类加载环境。

(2)打破双亲委派

  • 在某些特殊场景下,可能需要打破双亲委派机制。例如:

    • Tomcat:每个Web应用使用独立的类加载器,避免类冲突。

    • OSGi:动态模块化系统,支持模块化加载和卸载。


7. 实际应用场景

(1)Tomcat的类加载器

  • Tomcat为每个Web应用提供了一个独立的类加载器(WebAppClassLoader),打破了双亲委派机制。

  • 这样做的目的是隔离不同Web应用的类加载环境,避免类冲突。

(2)OSGi框架

  • OSGi是一个动态模块化系统,每个模块(Bundle)有独立的类加载器。

  • OSGi通过复杂的类加载机制,支持模块的动态加载和卸载。

(3)SPI(Service Provider Interface)

  • Java的SPI机制(如JDBC)打破了双亲委派机制。

  • 例如,java.sql.Driver接口由Bootstrap ClassLoader加载,而具体的驱动实现(如com.mysql.cj.jdbc.Driver)由Application ClassLoader加载。


8. 总结

双亲委派机制是Java类加载的核心机制,通过层次化的委派方式,确保类的加载安全、一致且高效。它的主要优点包括避免重复加载、保证安全性和一致性,但在某些场景下可能不够灵活,需要打破双亲委派机制。

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

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

相关文章

网络安全-js安全知识点与XSS常用payloads

简介 JavaScript 是一种轻量级的编程语言&#xff0c;定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系&#xff08;即没有关系&#xff09;。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…

ip属地是电话号码吗怎么改

在数字化时代&#xff0c;IP属地作为网络身份的一部分&#xff0c;对于许多互联网用户来说并不陌生。然而&#xff0c;关于IP属地的具体含义以及如何更改它&#xff0c;却常常让一些用户感到困惑。特别是当提到IP属地与电话号码之间的关系时&#xff0c;更是容易让人产生误解。…

Ubuntu中使用yum命令出现错误提示:Command ‘yum‘ not found

Ubuntu中使用yum命令出现以下错误提示: 解决方法如下 1、使用su或sudo -s命令使普通用户切换为root用户 2、然后检测是否安装了build-essential程序包,输入命令: apt-get install build-essential 3、进度走完后安装yum,输入命令: apt-get install yum 如果成功安装&#xff…

深入理解 JVM 的栈帧结构

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

[oeasy]python068_异常处理之后做些什么_try语句的完全体_最终_finally

068_异常处理之后做些什么_finally 异常处理之后做些什么_try语句的完全体_最终_finally 回忆上次内容 我们了解了 try 的细节 except 可以 捕获到异常 但报错比较简单 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 游乐场里面的 报错 更全 更丰富 …

PySide6学习专栏(四):用多线程完成复杂计算任务

如果计程序中要处理一个非常庞大的数据集中的数据&#xff0c;且数据处理计算很复杂&#xff0c;造成数据处理占用大量时间和CPU资源&#xff0c;如果不用多线程&#xff0c;仅在主进程中来处理数据&#xff0c;将会使整个程序卡死&#xff0c;必须采用多线程来处理这些数据是唯…

神经网络八股(1)

1.什么是有监督学习&#xff0c;无监督学习 有监督学习是带有标签的&#xff0c;无监督学习是没有标签的&#xff0c;简单来说就是有监督学习的输入输出都是固定的&#xff0c;已知的&#xff0c;无监督学习输入是已知的&#xff0c;输出是不固定的&#xff0c;无监督学习是通…

深度学习每周学习总结Y1(Yolov5 调用官方权重进行检测 )

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客Y1中的内容 &#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 ** 注意该训练营出现故意不退押金&#xff0c;恶意揣测偷懒用假的结果冒充真实打卡记录&#xff0c;在提出能够拿到视频录像…

计算机视觉基础|从 OpenCV 到频域分析

一、引言 在当今数字化时代&#xff0c;图像处理已渗透到我们生活的方方面面&#xff0c;从日常使用的智能手机拍照美化&#xff0c;到医学领域的精准诊断&#xff0c;再到自动驾驶中的环境感知&#xff0c;其重要性不言而喻。在图像处理领域中&#xff0c;OpenCV 和频域分析&…

74. 搜索二维矩阵(LeetCode 热题 100)

题目来源; 74. 搜索二维矩阵 - 力扣&#xff08;LeetCode&#xff09; 题目内容&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…

netcore libreoffice word转pdf中文乱码

一、效果 解决&#xff1a; cd /usr/share/fonts/ mkdir zhFont cd zhFont #windows系统C:\Windows\Fonts 中复制/usr/share/fonts/zhFont sudo apt update sudo apt install xfonts-utils mkfontscale mkfontdir #刷新字体缓存 fc-cache -fv #查看已安装的字体列表 fc-list :…

qt-C++笔记之创建和初始化 `QGraphicsScene` 和 `QGraphicsView` 并关联视图和场景的方法

qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 code review! 参考笔记 1.qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 2.qt-C笔记之QGraphicsScene和 QGraphicsView中setScene、通过scene得到view、通过…

OpenGL 01--构建GLFW、创建第一个工程、配置GLAD

一、OpenGL介绍 一般它被认为是一个API(Application Programming Interface, 应用程序编程接口)&#xff0c;包含了一系列可以操作图形、图像的函数。然而&#xff0c;OpenGL本身并不是一个API&#xff0c;它仅仅是一个由Khronos组织制定并维护的规范(Specification)。 OpenGL规…

【时时三省】(C语言基础)求多项式1-1/2+1/3-1/4+...+1/99-1/100的值 用C语言表示

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 示例&#xff1a; 输出结果是 0.688172

kafka-集群缩容

一. 简述&#xff1a; 当业务增加时&#xff0c;服务瓶颈&#xff0c;我们需要进行扩容。当业务量下降时&#xff0c;为成本考虑。自然也会涉及到缩容。假设集群有 15 台机器&#xff0c;预计缩到 10 台机器&#xff0c;那么需要做 5 次缩容操作&#xff0c;每次将一个节点下线…

Ubuntu22.04 - etcd的安装和使用

目录 介绍安装Etcd安装etcd的客户端使用 介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统&#xff0c;用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性&#xff0c;且客户端通过长连接watch 功能&#xff0c;能够及时收到数据变化…

排查JVM的一些命令

查看JVM相关信息的方法 环境&#xff1a; Win10, jdk17 查看端口的Pid netstat -ano | findstr <端口号>列出当前运行的JVM进程 ## 用于输出JVM中运行的进程状态信息。通过jps&#xff0c;可以快速获取Java进程的PID&#xff08;进程标识符&#xff09;&#xff0c; …

Arduino 第十六章:pir红外人体传感器练习

Arduino 第十六章&#xff1a;PIR 传感器练习 一、引言 在 Arduino 的众多有趣项目中&#xff0c;传感器的应用是非常重要的一部分。今天我们要学习的主角是 PIR&#xff08;被动红外&#xff09;传感器。PIR 传感器能够检测人体发出的红外线&#xff0c;常用于安防系统、自动…

自动化之ansible(二)

一、ansible中playbook&#xff08;剧本&#xff09; 官方文档&#xff1a; Ansible playbooks — Ansible Community Documentation 1、playbook的基本结构 一个基本的playbook由以下几个主要部分组成 hosts: 定义要执行任务的主机组或主机。 become: 是否需要使用超级用户…

QSNCTF-WEB做题记录

第一题&#xff0c;文章管理系统 来自 <天狩CTF竞赛平台> 描述&#xff1a;这是我们的文章管理系统&#xff0c;快来看看有什么漏洞可以拿到FLAG吧&#xff1f;注意&#xff1a;可能有个假FLAG哦 1&#xff0c;首先观察题目网站的结构和特征 这个一个文件管理系统&#x…