JVM 类加载器之间的层次关系,以及类加载的委托机制

JVM 类加载器之间存在一种层次关系,通常被称为双亲委派模型 (Parent Delegation Model)。这种层次关系和委托机制是 Java 类加载机制的核心,对于保证 Java 程序的安全性和避免类冲突至关重要。

1. 类加载器的层次关系:

JVM 中的类加载器(ClassLoader)主要分为以下几种,它们之间存在自顶向下的层次关系(父子关系,但不是继承关系,而是组合关系):

  • 启动类加载器 (Bootstrap Class Loader):

    • 最顶层的类加载器。
    • 负责加载 Java 核心类库,例如 java.langjava.utiljava.io 等包中的类(通常位于 <JAVA_HOME>/jre/lib 目录下的 rt.jarresources.jar 等)。
    • 用 C/C++ 实现,是 JVM 的一部分,不是 Java 类。
    • 没有父类加载器。
    • 无法通过 Java 代码直接获取到启动类加载器。
  • 扩展类加载器 (Extension Class Loader):

    • 父类加载器是启动类加载器。
    • 负责加载 Java 扩展类库(通常位于 <JAVA_HOME>/jre/lib/ext 目录下的 jar 包,或者由 java.ext.dirs 系统属性指定的目录)。
    • sun.misc.Launcher$ExtClassLoader 的实例(Java 类)。
  • 应用程序类加载器 (Application Class Loader / System Class Loader):

    • 父类加载器是扩展类加载器。
    • 负责加载应用程序的类(classpath 下的类,包括你写的代码、第三方库等)。
    • sun.misc.Launcher$AppClassLoader 的实例(Java 类)。
    • 通常是默认的类加载器。 可以通过 ClassLoader.getSystemClassLoader() 获取。
  • 自定义类加载器 (User-Defined Class Loader):

    • 父类加载器通常是应用程序类加载器(也可以是其他自定义类加载器)。
    • 由开发者自定义,继承 java.lang.ClassLoader 类。
    • 用于实现特殊的类加载逻辑,例如:
      • 从网络加载类。
      • 从数据库加载类。
      • 对类进行加密和解密。
      • 实现热部署(HotSwap)。
      • 实现模块化(OSGi)。

类加载器层次关系图示:

                     +-----------------------------+|  Bootstrap Class Loader     |  (C/C++)+-----------------------------+↑|  (Parent)|+-----------------------------+|  Extension Class Loader     |  (sun.misc.Launcher$ExtClassLoader)+-----------------------------+↑|  (Parent)|+-----------------------------+| Application Class Loader    |  (sun.misc.Launcher$AppClassLoader)+-----------------------------+↑|  (Parent)|+-----------------------------+|  User-Defined Class Loader  |  (extends java.lang.ClassLoader)+-----------------------------+

2. 双亲委派模型 (Parent Delegation Model):

  • 工作原理:

    1. 当一个类加载器需要加载类时,它首先不会自己尝试加载,而是 委托给它的父类加载器 去加载。
    2. 父类加载器会检查自己是否已经加载过该类。如果已经加载,则直接返回 Class 对象。
    3. 如果父类加载器没有加载过该类,则会尝试加载。如果父类加载器在其搜索范围内找到了该类,则加载成功,并返回 Class 对象。
    4. 如果父类加载器无法加载该类(在其搜索范围内找不到该类),则 将加载请求返回给子类加载器
    5. 子类加载器尝试加载该类。如果子类加载器能够加载,则加载成功,并返回 Class 对象。
    6. 如果子类加载器也无法加载该类,则抛出 ClassNotFoundException 异常。
  • 特例: 启动类加载器没有父类加载器,它会直接尝试加载。

  • 代码示例 (简化版):

    // java.lang.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 {// 3. 如果没有父类加载器 (到达了启动类加载器),则调用 findBootstrapClassOrNullc = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// 父类加载器无法加载该类}if (c == null) {// 4. 如果父类加载器无法加载,则调用 findClass 方法尝试自己加载c = findClass(name);}}if (resolve) {resolveClass(c); // 链接类 (可选)}return c;}
    }
    
    • findClass() 方法是需要子类加载器重写的方法, 用于实现自定义的类加载逻辑.

3. 双亲委派模型的优点:

  • 避免类的重复加载: 同一个类只会被加载一次,避免了命名冲突和资源浪费。
  • 保证 Java 核心类库的安全性: 用户自定义的类加载器无法加载或替换 Java 核心类库中的类(例如 java.lang.Objectjava.lang.String),因为核心类库总是由启动类加载器加载。这可以防止恶意代码篡改核心类库,破坏 JVM 的安全性。
  • 命名空间隔离: 不同的类加载器加载的类位于不同的命名空间, 可以防止类名冲突.

4. 破坏双亲委派模型:

虽然双亲委派模型有很多优点,但在某些情况下,可能需要破坏双亲委派模型,例如:

  • JDBC、JNDI、JAXP 等 SPI (Service Provider Interface) 机制:

    • 这些 API 的核心接口是由启动类加载器加载的,但具体的实现类通常由应用程序类加载器或自定义类加载器加载。
    • 为了解决这个问题,Java 引入了线程上下文类加载器 (Thread Context ClassLoader)。
    • 可以通过 Thread.currentThread().getContextClassLoader() 获取线程上下文类加载器。
    • 例如,JDBC 驱动程序通常由应用程序类加载器加载,但 JDBC API (如 java.sql.DriverManager) 需要能够加载这些驱动程序。DriverManager 会使用线程上下文类加载器来加载驱动程序。
  • OSGi (Open Service Gateway initiative):

    • OSGi 是一个模块化系统,每个模块(bundle)都有自己的类加载器。
    • OSGi 的类加载器模型不是严格的双亲委派模型,而是更复杂的网状结构。
  • 热部署 (HotSwap):

    • 在应用程序运行时,动态地替换或更新类。
    • 通常需要自定义类加载器,并破坏双亲委派模型。
  • Tomcat:

    • Tomcat 为了实现 web 应用之间的隔离,以及共享库的加载,破坏了双亲委派模型。
    • 每个 web 应用都有自己的类加载器 (WebAppClassLoader)。

总结:

JVM 类加载器之间存在层次关系(启动类加载器、扩展类加载器、应用程序类加载器、自定义类加载器),并通过双亲委派模型协同工作。双亲委派模型保证了类加载的顺序和安全性,避免了类的重复加载,并防止了核心类库被篡改。 在某些特殊情况下,可能需要破坏双亲委派模型(例如,SPI、OSGi、热部署)。

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

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

相关文章

基于 Vue 3 的PDF和Excel导出

以下是基于 Vue 3 Composition API 的完整实现&#xff0c;包括 PDF 和 Excel 导出。 一、PDF 导出 (Vue 3) 安装依赖 在项目中安装相关库&#xff1a; npm install html2canvas jspdf Vue 3 代码实现 <template><div><div ref"pdfContent" cla…

【Jupyter】notebook无法显示tqdm进度条

错误描述 from tqdm.notebook import tqdm 用的时候报错&#xff1a; Error displaying widget解决方式 # 先装nodejs conda install -c conda-forge nodejs20# 重装ipywidgets pip uninstall ipywidgets pip install ipywidgets jupyter labextension install jupyter-wid…

ubuntu20如何升级nginx到最新版本(其它版本大概率也可以)

前言&#xff1a; Nginx非常常用&#xff0c;所以在网络安全方面备受“关注”。其漏洞非常多&#xff0c;要经常保持软件更新版本才能更好的保证安全。但是Ubuntu官网适配nginx非常慢&#xff0c;所以nginx官方也会推出针对主流Linux操作系统的包管理工具安装方式。 步骤&…

word插入Mathtype公式居中和自动更新

word插入公式自动更新 前提&#xff1a;安装Mathtype 1.word中查看页的宽度 出现如下 2.设置样式 出现这个窗口 给样式随便起个名字 3.修改样式 3.1 设置两个制表位 第二个 3.2 修改公式字体 如下所示 4. 修改公式格式 4.1在word中打开 Mathtype 4.2 修改公式的格式 变成…

如何从后端实现页面跳转?

例&#xff1a;请求转发 例&#xff1a;重定向 例&#xff1a;区别&#xff1a;携带参数的后端跳转 例&#xff1a;是否可以访问外部资源 请求转发&#xff1a;客户端发起一个请求到服务端&#xff0c;服务端把这个请求转发至其他地方 重定向&#xff1a;客户端发起一个请求…

APIJSON快速入门

作者 版本 时间 内容 备注 Allen V1.0.0 2021/08/19 初稿完成 AllenV1.0.1 2021/08/22 添加常见问题 1.流程说明 一个接口的开发,比如Java用SpringBoot,Mybatis来开发一般来说就像下面这个流程 部署上这个项目后,流程变成了这样 如果使用 apijson-framework,还可进一步简化…

STM32八股【3】------RAM和片上FLASH

1、RAM和FLASH构成 1.RAM ┌──────────────────────────┐ │ 栈区 (Stack) │ ← 从RAM顶端向下扩展&#xff08;存储局部变量、函数调用信息&#xff09; │--------------------------│ │ 堆区 (Heap) │ ← …

基于springboot的星之语明星周边产品销售网站(050)

摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应洗衣店业务新的交流形式的网站。本文介绍了星之语明星周边产品销售网站的开发全过程。通过分析企业对于星之语明星周边产品销售网站的需求&#xff0c;创建了一…

Android Launcher3 HotSeat文件夹创建禁止方案全解析

一、技术背景与实现原理 在Android 13 Launcher3定制开发中&#xff0c;需屏蔽HotSeat区域的文件夹创建功能。该功能涉及的核心事件处理流程如下&#xff1a; 复制 [拖拽事件] -> [Workspace.onDrop()] -> [CellLayout.performReorder()]└─> [createUserFolderIf…

从零到一开发一款 DeepSeek 聊天机器人

AI聊天机器人 目标设计方案系统架构技术选型功能模块 实现代码环境配置安装依赖 核心代码API 请求函数主循环函数 功能扩展1. 情感分析2. 多语言支持3. 上下文记忆4. 用户身份识别 总结附录 目标 开发一个智能聊天机器人&#xff0c;旨在为用户提供自然、流畅的对话体验。通过…

OpenCV-Contrib常用扩展模块

‌一、高频使用模块‌ ‌aruco 模块‌ ‌功能‌&#xff1a;用于生成与检测二维码&#xff08;如 ArUco Marker、AprilTag&#xff09;&#xff0c;支持增强现实&#xff08;AR&#xff09;中的物体定位与姿态估计‌。‌典型应用‌&#xff1a;AR 应用中的场景锚定、机器人导航…

pfsense部署三(snort各版块使用)

在上篇文章上我们已经进行了snort的基础配置了&#xff0c;接下来需要进行snort的具体配置&#xff0c;其中包括各板块的设置&#xff0c;例&#xff1a;白名单&#xff0c;警报&#xff0c;规则设置等 规则库配置 点击 service > snort > Global Settings ,在code值…

汽车制造MES

一、整体生产工序 整车的车间主要分为4个部分&#xff1a;冲压、焊装、涂装、总装、整车入库 系统架构 二、车间概括 1.冲压车间 2.焊装车间 3.涂装车间 4.总装车间 1.整车装配的部件都要可追溯、数据实时性要求高、涉及分装与总装的协调、物流配送的协调、质量批处理的协调、…

python接口自动化pytest+request+allure

自己自学接口自动化过程遇到的问题及解决方法记录 首先是一个简单的请求 import requests#这是一个简单是get请求 def test_get():geturl https://so.csdn.net/api/v1/relevant-search?querypycharm%E5%AE%89%E8%A3%85requests%E5%BA%93&platformpcgetr requests.get(…

CompletableFuture的使用

CompletableFuture 是 Java 8 引入的异步编程工具&#xff0c;通过链式调用和非阻塞操作简化多线程任务编排。 创建异步任务 1.带返回值的任务 CompletableFuture<String> future CompletableFuture.supplyAsync(() -> "Hello");2. ​无返回值的任务 使…

GLB文件介绍

GLB文件是由支持glTF&#xff08;GL Transmission Format&#xff09;标准的软件或工具生成的。glTF是一种开放的3D模型传输格式&#xff0c;而GLB是其二进制版本&#xff0c;通常用于嵌入纹理和模型数据。以下是常见的生成GLB文件的软件和工具&#xff1a; 1. 3D建模软件 • …

计算机网络的分类及其性能指标

一. 计算机网络的分类 1. 按分布范围分类 广域网&#xff08;WAN&#xff09; 也称远程网。广域网提供长距离通信&#xff0c;通常是几十千米到几千千米的区域&#xff0c;比如跨国通信。连接广域网的各结点交换机的链路一般是高速链路&#xff0c;具有较大的通信容量城域网&…

gralloc usage flags

下面这些示例主要说明了 gralloc usage flags 在图像处理和多媒体应用中如何影响性能和正确性。让我们逐个详细分析每个问题的 根因 和 修复方案&#xff0c;并深入解析 gralloc 标志对 缓存管理 和 数据流 的影响。 ✅ Example 1: 长曝光快照耗时异常 &#x1f4cc; 问题描述…

关于kafka的一些知识总结

Kafka 1. 基本知识 1.1 前置知识 topic表示一个类型/业务的数据的组为方便扩展&#xff0c;提高吞吐率&#xff0c;一个topic分为多个partition。配合分区的设计&#xff0c;提出消费者组的概念&#xff0c;每个消费者并行消费&#xff0c;同时&#xff0c;一个分区的数据&a…

深入理解traceroute命令及其原理

traceroute 是一个网络诊断工具&#xff08;Windows上叫tracert&#xff09;&#xff0c;用于显示数据包从本地主机到远程主机经过的路由&#xff08;跳数&#xff09;。它可以帮助您了解数据包在网络中的传输路径&#xff0c;以及每跳的延迟情况。这对于网络故障排除、分析网络…