JVM 类加载器之间的层次关系,以及类加载的委托机制
JVM 类加载器之间存在一种层次关系,通常被称为双亲委派模型 (Parent Delegation Model)。这种层次关系和委托机制是 Java 类加载机制的核心,对于保证 Java 程序的安全性和避免类冲突至关重要。
1. 类加载器的层次关系:
JVM 中的类加载器(ClassLoader)主要分为以下几种,它们之间存在自顶向下的层次关系(父子关系,但不是继承关系,而是组合关系):
-
启动类加载器 (Bootstrap Class Loader):
- 最顶层的类加载器。
- 负责加载 Java 核心类库,例如
java.lang
、java.util
、java.io
等包中的类(通常位于<JAVA_HOME>/jre/lib
目录下的rt.jar
、resources.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):
-
工作原理:
- 当一个类加载器需要加载类时,它首先不会自己尝试加载,而是 委托给它的父类加载器 去加载。
- 父类加载器会检查自己是否已经加载过该类。如果已经加载,则直接返回
Class
对象。 - 如果父类加载器没有加载过该类,则会尝试加载。如果父类加载器在其搜索范围内找到了该类,则加载成功,并返回
Class
对象。 - 如果父类加载器无法加载该类(在其搜索范围内找不到该类),则 将加载请求返回给子类加载器。
- 子类加载器尝试加载该类。如果子类加载器能够加载,则加载成功,并返回
Class
对象。 - 如果子类加载器也无法加载该类,则抛出
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.Object
、java.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、热部署)。
相关文章:
JVM 类加载器之间的层次关系,以及类加载的委托机制
JVM 类加载器之间存在一种层次关系,通常被称为双亲委派模型 (Parent Delegation Model)。这种层次关系和委托机制是 Java 类加载机制的核心,对于保证 Java 程序的安全性和避免类冲突至关重要。 1. 类加载器的层次关系: JVM 中的类加载器(Cl…...
吞吐与时延的博弈,超发与冗余的交换
做传输协议加速,大家默认激进超发原则,却认为冗余双发不道德,其实这两个是一回事,它们本质上是一种 “矩” 内的交换,就像力和力臂交换但乘积不变一样,成本是固定的。 人们更能原谅激进超发是因为人们对吞…...
Jackson使用ObjectNode对象实现JSON对象数据(一):增、删、改、查
Jackson 是一款高性能的 Java JSON 处理库,广泛应用于 Java 对象的序列化(转为JSON)与反序列化(JSON转为对象)。作为 Spring MVC 默认的JSON解析器,其核心优势包括高性能、灵活性和丰富的功能支持。 Jackson 库中 ObjectNode 是操作 JSON 对象的核心类,…...
【递归、搜索和回溯算法】专题三 :穷举VS暴搜VS深搜VS回溯VS剪枝
回溯算法 回溯算法是一种经典的递归算法,通常用于解决组合问题、排列问题和搜索问题等。 基本思想:从一个初始状态开始,按照一定的规则向前搜索,当搜索到某个状态无法前进时,回退到钱一个状态,再按照其他的…...
Ubuntu如何部署AI-Sphere-Butler(metahuman-stream)
环境: Ubuntu 20.04、22.04 Python3.10 Pytorch 1.12 CUDA 11.3 问题描述: Ubuntu如何部署AI-Sphere-Butler(metahuman-stream(LiveTalking)) 解决方案: 一、部署 本次部署以云服务器&a…...
基于开源模型的微调训练及瘦身打造随身扫描仪方案__用AI把手机变成文字识别小能手
基于开源模型的微调训练及瘦身打造随身扫描仪方案__用AI把手机变成文字识别小能手 一、准备工作:组装你的"数码工具箱" 1. 安装基础工具(Python环境) 操作步骤: 访问Python官网下载安装包安装时务必勾选Add Python to…...
SpringBoot分布式定时任务实战:告别重复执行的烦恼
场景再现:你刚部署完基于SpringBoot的集群服务,凌晨3点突然收到监控告警——优惠券发放量超出预算两倍!检查日志发现,两个节点同时执行了定时任务。这种分布式环境下的定时任务难题,该如何彻底解决? 本文将…...
第十二章 | Solidity 智能合约前后端集成实战
📚 第十二章 | Solidity 智能合约前后端集成实战 ——链上合约 前端钱包 用户交互,打造完整 DApp! 这章我们正式进入 DApp 全栈开发领域! 用 Ethers.js React/Vue 完成前端和合约交互完整的「前端发起交易 → 钱包签名 → 链上…...
sqlite3数据库(文件)损坏恢复方法
问题描述 实时控制系统在运行过程中,我使用DB Browser for SQLite工具写sqlite数据库操作,工具异常退出,再次使用此工具打开数据文件时,数据文件打不开,报错:invalid rootpage,如何处理? 解决…...
正则艺术:深入探讨高级语法——零宽断言与反向引用实战
正则艺术:深入探讨高级语法——零宽断言与反向引用实战 在 Python 这门语言中,正则表达式无疑是一把神奇的钥匙。它不仅能够轻松实现字符串匹配、替换和拆分,更在数据清洗、日志分析、爬虫开发等场景中大放异彩。作为一名拥有多年实战与教学经验的 Python 程序专家,今天我…...
python——UI自动化(1) selenium之介绍和环境配置
一、selenium介绍 selenium是一个第三方库,python有很多库; 1、什么是ui自动化? 通过模拟手工操作用户ui页面的方式,用代码去实现自动化操作和验证的行为。 2、ui自动化的优点? (1)解决重复性的功能测…...
专题|Python贝叶斯网络BN动态推理因果建模:MLE/Bayes、有向无环图DAG可视化分析呼吸疾病、汽车效能数据2实例合集
原文链接:https://tecdat.cn/?p41199 作为数据科学家,我们始终在探索能够有效处理复杂系统不确定性的建模工具。本专题合集系统性地解构了贝叶斯网络(BN)这一概率图模型在当代数据分析中的创新应用,通过开源工具bnlea…...
MQ,RabbitMQ,MQ的好处,RabbitMQ的原理和核心组件,工作模式
1.MQ MQ全称 Message Queue(消息队列),是在消息的传输过程中 保存消息的容器。它是应用程序和应用程序之间的通信方法 1.1 为什么使用MQ 在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理࿰…...
STM32__红外避障模块的使用
目录 一、红外避障模块 概述 二、直接读取OUT引脚电平 三、使用中断方式触发 一、红外避障模块 概述 引脚解释: VCC接3.3V 或 5.0VGND接开发板的GNDOUT数字量输出(0或1); 低电平时表示前方有障碍 ; 通过可调电阻调整检测距离 产品特点: …...
第三天 开始Unity Shader的学习之旅之第二天的补充
Unity Shader的学习笔记 第三天 开始Unity Shader的学习之旅之第二天的补充 文章目录 Unity Shader的学习笔记前言一、Unity 提供的内置文件和变量1. 内置的包含文件2. UnityCG.cginc中的常用结构体 二、Unity 提供的Cg/HLSL语义1. 从应用阶段传递模型数据给顶点着色器时Unity…...
文献分享: ColXTR——将ColBERTv2的优化引入ColXTR
1. ColXTR \textbf{1. ColXTR} 1. ColXTR原理 1.1. ColBERTv2 \textbf{1.1. ColBERTv2} 1.1. ColBERTv2概述 1.1.1. \textbf{1.1.1. } 1.1.1. 训练优化 1️⃣难负样本生成 初筛:基于 BM-25 \text{BM-25} BM-25找到可能的负样本重排:使用 KL \text{KL} KL…...
【第21节】windows sdk编程:网络编程基础
目录 引言:网络编程基础 一、socket介绍(套接字) 1.1 Berkeley Socket套接字 1.2 WinSocket套接字 1.3 WSAtartup函数 1.4 socket函数 1.5 字节序转换 1.6 绑定套接字 1.7 监听 1.8 连接 1.9 接收数据 1.10 发送数据 1.11 关闭套接字 二、UDP连接流程…...
《深度剖析:BERT与GPT——自然语言处理架构的璀璨双星》
在自然语言处理(NLP)的广袤星空中,BERT(Bidirectional Encoder Representations from Transformers)与GPT(Generative Pretrained Transformer)系列模型宛如两颗最为耀眼的星辰,引领…...
景联文科技:以高质量数据标注推动人工智能领域创新与发展
在当今这个由数据驱动的时代,高质量的数据标注对于推动机器学习、自然语言处理(NLP)、计算机视觉等领域的发展具有不可替代的重要性。数据标注过程涉及对原始数据进行加工,通过标注特定对象的特征来生成能够被机器学习模型识别和使…...
LeetCode 30 —— 30.串联所有单词的子串
题目: 给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。 注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。 示例 1ÿ…...
【redis】主从复制:单点问题、配置详解、特点详解
文章目录 单点问题什么是主从复制主从模式能解决的问题并发量有限可用性问题 配置建立复制通过配置文件来指定端口配置主从查看集群结构 断开复制 特点安全性只读传输延迟 单点问题 分布式系统中,涉及到一个非常关键的问题:单点问题 某个服务器程序&…...
VSCode创建VUE项目(四)增加用户Session管理
将用户信息存储或者更新到Session sessionStorage.setItem("userID",loginform.value.username); sessionStorage.setItem(loginTime, Date.now()); 获取Session信息 const storedUserInfo sessionStorage.getItem(userID); const loginTime sessionStorage.get…...
Spring Boot(十六):拦截器Interceptor
拦截器的简介 拦截器(Interceptor)是Spring框架中的概念,它同样适用于Spring Boot,因为Spring Boot是基于Spring框架的。拦截器是一种AOP(面向切面编程)的轻量级实现方式,它允许我…...
考研复习之队列
循环队列 队列为满的条件 队列为满的条件需要特殊处理,因为当队列满时,队尾指针的下一个位置应该是队头指针。但是,我们不能直接比较 rear 1 和 front 是否相等,因为 rear 1 可能会超出数组索引的范围。因此,我们需…...
sql-labs
p1 sql注入的目的是为了破坏sql语句结构,有三种参数类型,字符型(就是一个字符1或者a之类的),字符串(“hellow之类的”)型,数值型,前两个有闭合,注释符号有# …...
Java 集合框架:从数据结构到性能优化,全面解析集合类
Java 集合框架(Java Collections Framework,JCF)是 Java 语言中用于存储、操作和管理数据的标准库。它提供了一组通用的接口、类和方法,使开发者能够高效地操作不同类型的数据集合。 本文将结合 Java 集合框架类图,介…...
vulkanscenegraph显示倾斜模型(5.4)-相机操纵器
前言 在VSG(Vulkan Scene Graph)中,系统支持用户通过鼠标或触摸输入与三维场景进行交互,从而动态控制相机的位置和姿态,实现与三维场景的交互。VSG提供了多种相机操纵器,其中Trackball是一种常见的相机操作…...
两个还算好用的ppt转word和PDF转word的python脚本
PPT转word: import re from pptx import Presentation from docx import Document from docx.shared import Inches from io import BytesIO from PIL import Imagedef clean_text(text):# 使用正则表达式删除控制字符和NULL字节return re.sub(r[\x00-\x1F\x7F], ,…...
用PostgreSQL玩转俄罗斯方块:当SQL成为游戏引擎
当DBA开始摸鱼2025年某深夜,一位不愿透露姓名的DBA为了在监控大屏上隐藏游戏行为,竟用SQL实现了俄罗斯方块!从此,SELECT成了方向键,UPDATE成了旋转指令,DELETE成了消除大招。本文将揭秘这个疯狂项目的技术内…...
基于WebAssembly的浏览器密码套件
目录 一、前言二、WebAssembly与浏览器密码套件2.1 WebAssembly技术概述2.2 浏览器密码套件的需求三、系统设计思路与架构3.1 核心模块3.2 系统整体架构图四、核心数学公式与算法证明4.1 AES-GCM加解密公式4.2 SHA-256哈希函数五、异步任务调度与GPU加速设计5.1 异步任务调度5.…...
手撕算法之`vector` 扩容、`string` 分割、链表翻转
手写常见操作:vector 扩容、string 分割、链表翻转 (一)vector扩容 在 C++ 中,vector 的扩容机制是动态数组实现的核心特性,直接关系到性能和内存使用效率。以下是深入剖析: 1. 扩容触发条件 vector<int> v; v.push_back(1); // 当 size() == capacity() 时触发…...
tauri2程序单例模式实现,二次点击桌面图标显示之前最小化的程序并聚焦
官方有这个单例的插件可以直接使用:单例 | Tauri,使用单实例插件确保 Tauri 应用程序在同一时间只运行单个实例。插件已经安装并初始化,应该可以立即正常运行。尽管如此,我们也可以使用 init() 方法来增强它的功能。插件的 init()…...
【AI学习笔记】Coze平台实现将Excel文档批量导入数据库全过程
背景前摇&原视频教程: 最近看到很多同学都在用Coze平台操作数据,我也想了解一下工作流的搭建和数据处理过程,但是一下子又看不懂太复杂的逻辑,于是上B站搜索相关的基础教程。 Coze官方教程: 之前有看过Coze平台…...
c++之迭代器
一.迭代器的基本概念 1.什么是迭代器 迭代器是一种对象,它提供了一种访问容器中各个元素的方法,同时隐藏了容器内部的实现细节。简单来说,迭代器就像是一个指针,它可以指向容器中的某个元素,并且能够通过一些操作&am…...
Elasticsearch 索引
一、简介 在 Elasticsearch 中,索引(Index)是存储相关文档的地方,类似于关系数据库中的数据库。索引是 Elasticsearch 中最重要的概念之一,用于组织和存储数据。 二、索引的基本概念 索引(Index…...
Java EE(16)——网络原理——TCP协议解析二
4.滑动窗口(效率机制) 上篇博客讲到的确认应答/超时重传/连接管理都是安全机制,但也会降低传输效率。滑动窗口就是在保证可靠传输的基础上,尽可能地提高传输效率。 根据确认应答机制,客户端每发送一个请求都需要收到服务器的确认应答报文后才…...
解决address already in use报错:如何查看占用某个端口的程序并杀死
文章目录 问题背景解决策略概述端口占用诊断步骤 1:确认占用端口的进程步骤 2:确认进程的详细信息 解决端口占用问题方案 1:安全终止进程方案 2:修改应用配置 最佳实践与预防措施端口使用规范开发环境配置 进阶技巧批量处理端口占…...
linux 设置tomcat开机自启动
tomcat自启动配置 1.添加tomcat.service文件 vim /etc/systemd/system/tomcat.service 2.编辑文件内容,路径修改为自己的 [Unit] DescriptionTomcat8 Aftersyslog.target network.target remote-fs.target nss-lookup.target[Service] Typeoneshot ExecStart/us…...
如何配置本地git
配置本地 Git 主要包含设置用户信息、配置 SSH 密钥、设置 Git 仓库等步骤,以下是详细的配置过程: 1. 安装 Git 在开始配置之前,你需要先安装 Git。不同操作系统的安装方式有所不同: Windows:访问 Git 官方下载页面&a…...
VSCode 生成HTML 基本骨架
在VSCode 新建html文件中敲一个英文感叹号 ! <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…...
蓝桥杯备考:DFS暴搜之健康的荷斯坦奶牛
这道题数据量很小很小,我们可以用dfs暴搜来搜索 这是我们的决策树 #include <iostream> using namespace std; int n, m; const int N 45; int rq[N]; int g[N][N]; int cnt; int path; int ret 45; int st; bool check() {for (int i 1; i < n; i){in…...
android adjust 卸载与重装监测
想要洞察应用内用户的留存率,可以通过Adjust 的卸载与重装进行监测 名词解释: 卸载:集成完成后,卸载应用,安装状态为:卸载 重装:如果应用已经卸载,但一段时间后又进行安装,则会被视为重装。 📢📢📢:adjust 文件中说到24 小时后,可以再 adjust 控制台看安装…...
WPF Reactive 数据绑定
文章目录 Combox 绑定List-通过枚举绑定方法一:方法二:Button 绑定TextBlock绑定NumericUpDown绑定Expander绑定checkbox绑定NumericUpDownCombox 绑定List-通过枚举绑定 方法一: ViewControl using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; usin…...
2.创建Collection、添加索引、加载内存、预览和搜索数据
milvus官方文档 milvus2.3.1的官方文档地址: https://milvus.io/docs/v2.3.x 使用attu创建collection collection必须要有一个主键字段、向量字段 确保字段类型与索引类型兼容 字符串类型(VARCHAR)通常需要使用 Trie 索引,而不是 AutoInd…...
yaffs
YAFFS(Yet Another Flash File System)是专为NAND闪存设计的日志结构文件系统,其核心原理围绕NAND闪存的特性优化数据管理。以下是其关键原理的详细说明: 1. NAND闪存适配 写入限制:NAND闪存需按页写入(通…...
CMake-环境变量介绍
文章目录 作用域获取环境变量初始化查看特殊的环境变量 环境变量类似普通变量,但也有些不同,如下: 作用域 在一个CMake进程中环境变量具有全局作用域 获取环境变量 使用ENV操作符获取环境变量,例如$ENV{<name>}ÿ…...
wordpress表单插件CF7调用方式
Contact Form 7(CF7)是WordPress中非常流行的表单插件,以下是其常见的调用方式: 通过短代码调用 在页面或文章编辑器中添加:完成表单设置后,复制表单对应的短代码,然后在需要显示表单的页面或文章的编辑器中直接粘贴…...
小程序开发中的用户反馈收集与分析
我们在开发小程序的过程中根据开发过程中的代码及业务场景,以下是针对需求管理系统的用户反馈收集与分析方案设计: 需求管理系统用户反馈收集与分析方案 一、反馈数据模型设计 // 新增Feedback模型(app/admin/model/Feedback.php) namespace app\admin\model; use think\…...
【HarmonyOS Next】鸿蒙中App、HAP、HAR、HSP概念详解
【HarmonyOS Next】鸿蒙中App、HAP、HAR、HSP概念详解 (图1-1) 一、鸿蒙中App、HAP、HAR、HSP是什么? (1)App Pack(Application Package) 是应用发布的形态,上架应用市场是以App Pa…...
Linux:一些命令记录
netstat -antp|grep -i 27017 | awk {print $5}| cut -d: -f1 | sort | uniq -c | sort -n 查看磁盘大小 du -sh /usr/local/* 查看剩余内存: free -m linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -1;ps aux|gr…...