JVM -- 类加载器
类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现访问接口和类字节码数据的技术。类加载器只负责加载过程中的字节码获取并加载到内存的这一过程。
一、 类加载器的分类
类加载器的详细信息可以使用Arthas通过classloader命令查看:
1.启动类加载器(Bootstrap ClassLoader)
由Hotspot虚拟机提供的,使用C++编写的类加载器,默认加载Java安装目录/jre/lib下的类文件。针对用户自定义的jar包如果想被启动类加载器加载的话,可以使用如下参数进行加载:
-Xbootclasspath/a:jar包目录/jar包名
加载java中最核心的类。
2. 扩展类加载器(Extension Class Loader)
使用JAVA编写,由JDK提供,源码位于sun.misc.Launcher,是一个静态内部类,继承自URLClassLoader。默认加载java安装目录的/jre/lib/ext下的文件,使用如下参数使用扩展类加载器进行加载:
-Djava.ext.dirs=jar包目录 进行扩展,这种方 式会覆盖掉原始目录,可以用;(windows):(macos/linux) 追加上原始目录
3. 应用类加载器(App CLass Loader)
使用JAVA编写,由JDK提供,源码位于sun.misc.Launcher,是一个静态内部类,继承自URLClassLoader。加载的是位于classpath下的文件
二、 双亲委派机制
双亲委派机制主要是为了解决:
- 同一个类被多次加载或者一个类应该被谁加载的问题;
- 保证类加载的安全性:避免恶意代码替换JDK中的核心类库。
启动类加载器、扩展类加载器、应用类加载器的关系如下:
[arthas@106672]$ classloader -t
+-BootstrapClassLoader+-sun.misc.Launcher$ExtClassLoader@79acc872 +-com.taobao.arthas.agent.ArthasClassloader@7b94591c+-sun.misc.Launcher$AppClassLoader@18b4aac2
应用程序类加载器的父类是扩展类加载器。而扩展类加载器的parent为null,但是在逻辑上,扩展类加载器依然会把启动类加载器当作夫类加载器处理。
启动类加载器使用C++编写,没有父类加载器。
逻辑:当一个类去加载某个类的时候,会自底向上查找是否加载过,如果加载过就直接返回,如果到底一直没有加载过,再由顶向下委派进行加载。
三、 打破双亲委派机制
打破的原因:一个Tomcat可以部署多个Web应用,如果两个应用中出现了相同限定名的类,比如Servlet类,Tomcat要保证这两个类都能加载并且它们应该是不同的类。
ClassLoader类中实现双线委派方式原理:
双亲委派的核心代码:
try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}
} catch (ClassNotFoundException e) {if (c == null) {// If still not found, then invoke findClass in order to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statessun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();
}
1. 自定义类加载器
自定义类加载器,重写loadClass(),不再使用双亲委派机制,而使用自己实现的loadClass()。
其中自定义类加载器的父加载器为:应用类加载器(getSystemClassLoader())
问题:两个自定义类加载器加载相同限定名的类,是否会冲突?
不会,只有同一个类加载器且加载相同限定名的才会被认定为同一个类。
2. 线程上下文类加载器
以DriverManager为例:
核心逻辑就是:启动类加载器加载DriverManager,在初始化DriverManager时会通过SPI机制加载mysql驱动,SPI机制利用了线程上下文来加载并创建对象,实现原本应该由启动类加载器交由应用类加载器去加载的过程,打破双亲委派机制。
依赖于SPI机制:rt.jar核心包是有Bootstrap类加载器加载的,其内包含SPI核心接口类,由于SPI中的类经常需要调用外部实现类的方法,而jdbc.jar包含外部实现类(jdbc.jar存在于classpath路径)无法通过Bootstrap类加载器加载,因此只能委派线程上下文加载器的加载方式破坏了“双亲委派模型”,它在执行过程中抛弃双亲委派加载链模式,使程序可以逆向使用类加载器,当然这也使得Java类加载器变得更加灵活。为了进一步证实这种场景,不妨看看DriverManager类的源码,DriverManager是Java核心rt.jar包中的类,该类用来管理不同数据库的实现驱动即Driver,它们都实现了Java核心包中的java.sql.Driver接口,如mysql驱动包中的com.mysql.jdbc.Driver
AccessController.doPrivileged(new PrivilegedAction<Void>() {public void run() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();}
}
实现延迟服务提供者查找
DriverManager.loadInitialDrivers -> ServiceLoader.load -> reload ->lookupIterator = new LazyInterator(service, loader);
加载meta-inf,初始化驱动
loadedDrivers.iterator() -> driversIterator.hasNext() -> hasNextService ->
ClassLoader.getSystemResources(fullName);
这样ServiceLoader会帮我们处理一切,并最终通过load()方法加载
3. Osgi框架的类加载器
历史上,OSGi模块化框架。它存在同级之间的类加载器的委托加载(如下图的加载器1和2)。OSGi还使用类加载器实现了热部署的功能。热部署指的是在服务不停止的情况下,动态地更新字节码文件到内存中。JDK9之后不再使用OSGi,现在可以使用arthas解决热部署问题。
由于这种机制使用已经不多,所以不再过多讨论OSGI
相关文章:

JVM -- 类加载器
类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现访问接口和类字节码数据的技术。类加载器只负责加载过程中的字节码获取并加载到内存的这一过程。 一、 类加载器的分类 类加载器的详细信息可以使用Arthas通过classloader命令查看: 1.启动类加载器(Boots…...

OLAP引擎之StarRocks
StarRocks 是一款新兴的开源分布式实时分析型数据库,专为高性能、高并发的数据分析场景设计。它结合了传统数据仓库和大数据技术的优势,提供了强大的实时数据处理和分析能力。以下是对 StarRocks 的详细介绍,涵盖其基本概念、核心特性、架构设…...

基于微信小程序的小区业主服务系统(源码+论文+部署讲解等)
博主介绍:✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术栈介绍:我是程序员阿龙ÿ…...

C++ | Leetcode C++题解之第327题区间和的个数
题目: 题解: class Solution { public:int countRangeSumRecursive(vector<long>& sum, int lower, int upper, int left, int right) {if (left right) {return 0;} else {int mid (left right) / 2;int n1 countRangeSumRecursive(sum,…...

C# Winform 多窗体切换方式一
一、简介 在 Winform 开发中,多窗体的切换是一个常见的需求,比如登录成功后,切换至主界面,在网上查阅相关的资料,你会发现很多都是用 form2.Show(); this.Hide(); 这种方式,这种方式也存在一些问题&#…...

笔记本CPU天梯图(2024年8月),含AMD/骁龙等新CPU
原文地址(高清无水印原图/持续更新/含榜单出处链接): 2024年8月笔记本CPU天梯图 2024年8月笔记本CPU天梯图 2024年8月5日更新日志:常规更新Cinebench R23、PassMark笔记本CPU天梯图,新增Geekbench 6.2单核多核天梯图&…...

GitLab-CI/CD指南
由于公司没有运维,写go服务时各个环境编译部署还是略显麻烦,由于代码管理使用的是 gitlab,所以决定使用 gitlab 自带的 CI/CD 来做自动编译和部署,这样每次提交代码以后就可以自动部署到服务器上了。 gitlab 本身只有 CI/CD 的接…...

io目录操作学习
1、基本概念 目录也是一种文件,因此操作流程与普通文件类似,有诸如打开、关闭、定位等概念,但目录是一种特殊的文件,目录存储的数据的最小单位并不是字符,而是目录项。这使得目录跟普通文件又有区别。 在Linux中&…...
Ant-Design-Vue
Ant-Design-Vue是蚂蚁金服Ant Design官方推荐的Vue版UI组件库,它继承了Ant Design的设计语言和Vue.js的易用性,为开发者提供了丰富、高质量的Vue组件,极大地简化了前端开发流程。以下是一份详细的Ant-Design-Vue快速上手指南及排坑建议&#…...
2024互联网暑期实习面经和流程记录分享
2024互联网暑期实习面经和流程记录分享 面试经验和流程需要注意的点 面试经验和流程 因为敏感信息的原因,这里涉及到公司名字的全部进行打码 笔者投递和面试了很多公司,具体有包括算法和开发岗,下面的公司一律用字母代替。 O公司࿰…...

风云崛起之拉氏变换和拉式逆变换
图像的分割写出来了,但是写的不好,暂时先不发了。这两天小y想在把拉式变换的内容写出来,小y最近再看信号和电路,需要复习数学,所以把这点写出来。 首先要推出分布积分的公式,我们知道积分和微分为逆运算&am…...

1、.Net UI框架:WinUI - .Net宣传系列文章
WinUI(Windows UI Library)是微软提供的一个用于构建Windows应用程序的本机UI平台组件。它与Windows应用SDK紧密相关,允许开发者创建适用于Windows 10及更高版本的应用程序,并且可以发布到Microsoft Store。WinUI 3是最新的一代,它提供了与操…...
计算机的错误计算(五十九)
摘要 讨论用 Go语言实现的 函数的计算精度问题。 由计算机的错误计算(五十五)知,国际 IEEE 754 标准中, 函数具有定义域 . 那么,在常规编程模式下用 Go语言实现这个函数,其输出的精度如何? …...
【数学分析笔记】第1章第1节:集合(1)
作为一个计算机专业的人,想自学一下数学专业的专业课补一补AI基础,顺带写个笔记,听的课是陈纪修版本的数学分析: 1. 集合与映射 1.1 集合 1.1.1 基本概念 集合:由某种特定性质的具体的或抽象的对象汇集的总体。 集…...

计算机毕业设计 校园失物招领网站 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
GIT指令大全详解
目录 GIT指令详解 拉取 提交 分支操作(假设分支为a) 版本回退 主分支拉取到分支 常用的Git指令 一、初始化配置 二、初始化仓库 三、检查当前文件状态 四、添加 五、查看提交历史 六、撤销更改 七、查询 八、分支 九、标签管理 十、其他常用指令 GIT指令详解 Git是一个开源的分…...

ECCV2024,清华百度提出ReSyncer:可实现音频同步嘴唇动作视频生成。
清华&百度等联合提出了ReSyncer,可以实现更高稳定性和质量的口型同步,而且还支持创建虚拟表演者所必需的各种有趣属性,包括快速个性化微调、视频驱动的口型同步、说话风格的转换,甚至换脸。 ReSyncer的工作原理可以简单理解为…...

论文笔记:YOLOv8-QSD 自动驾驶场景小目标检测算法
摘要 YOLOv8-QSD网络是一种新型的无锚点驾驶场景检测网络,建立在YOLOv8的基础上,在保证检测精度的同时保持效率。该网络的骨干网采用结构重参数化技术来转换基于多样化分支块 (DBB) 的模型。 为了准确检测小目标,它集…...
Vue.js状态管理:Vuex与Pinia的比较
在 Vue.js 生态系统中,状态管理是构建复杂应用时的重要组成部分。Vue.js 提供了两种流行的状态管理库:Vuex 和 Pinia。虽然两者都旨在简化状态管理,但它们在设计哲学、API、性能和易用性方面有所不同。本文将深入探讨 Vuex 和 Pinia 的异同&a…...

OJ题目【栈和队列】
目录 有效的括号 有效的括号【代码】 用队列实现栈 用队列实现栈【代码】 用栈实现队列 用栈实现队列【代码】 设计循环队列 有效的括号 https://leetcode.cn/problems/valid-parentheses/submissions/551394950/ 思路:把左括号放到栈里,取出来栈…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...