双亲委派机制SPI

SPI如何破坏双亲委派机制?可根据以下概念一步步深入

什么是双亲委派机制?

双亲委派机制是Java类加载器体系中采用的一种类加载策略,旨在保证类加载的安全性和稳定性。

这一机制规定了类加载的顺序和规则,即当一个类加载器收到类加载请求时,首先不会自己去尝试加载这个类,而是将这个任务委托给它的父类加载器去完成,只有当父加载器无法加载该类时(表现为抛出ClassNotFoundException),才会尝试自己加载。

 

优点:核心的包,谁也改变不了,保证了安全性。

缺点:在于它的隔离性,Bootstrap加载器无法去加载应用程序的类。(后面就引出SPI的概念)

1 先去自定义加载器加载,自定义加载器没有加载过这个类,委派给应用类加载器

2 应用类加载器也没有加载过这个类,委托给扩展类加载器

3 扩展类加载器没有加载过这个类,委托给根加载器,根加载器去rt.jar的包里去找需要加载的类,rt.jar包里没有,就让扩展类加载器去ext路径下去找

4 扩展类加载器也没有找到,就让应用类加载器去CLASSPATH下面找…

举例验证:当你自定义一个java.lang.String的类,去new这个对象时,加载的仍然是Java自带的String对象,而不是你自定义的String对象。(详细如下图)

什么是SPI?

SPI全称ServiceProviderInterface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。SPI的作用就是为这些被扩展的API寻找服务实现。

SPI使用方式?

1 定义一个接口,并创建它的实现类

2 然后在项目的src/main/resource/META-INF/services目录下创建一个与上述接口的全限定名一致的文件,在这个文件中写入接口的实现类的全限定名

3 运行时,会查找加载这些实现类。(比如下面举例的加载mysql驱动程序)

为什么你在自己的JDBC项目中没有找到META-INF/services/java.sql.Driver文件?

如果你的项目是直接使用像Spring Boot这样的现代框架,它们通常有自动配置或者依赖管理特性,能自动处理JDBC驱动的加载,而不需要你手动放置这个文件。特别是当你通过Maven或Gradle等构建工具管理依赖时,驱动的SPI配置已经是驱动包内部的事情,你的项目不需要直接包含这个文件。

什么是rt.jar?

rt.jar 是 Java Runtime Environment (JRE) 的一个核心组件,全称为 Runtime JAR

如何“破坏”?

SPI核心类在rt.jar 位于Bootstrap ClassLoader启动类加载器中,但是SPI需要实现来自不同厂商提供的数据库Driver实现类,而这些来自不同厂商的SPI接口实现类(如com.mysql.cj.jdbc.Driver)位于Application ClassLoader应用类加载器中

为何说“破坏”?

尽管SPI本身是由启动类加载器加载,但是它间接的通过应用类加载器加载第三方驱动类,绕过了严格的双亲委派机制

为什么要破坏?

因为使用双亲委派有一定的局限性,在正常情况下,用户代码一定是依赖核心类库的,所以双亲委派加载机制是没有问题的,但是在加载核心类库时,又要反过来使用用户代码,双亲委派就无法满足。这是什么样的一个场景呢?比如jdbc利用Driver.Manager.getConnection获取连接时,DriverManager是由根类加载器Bootstrap ClassLoader加载的,在加载DriverManager时,会执行其静态方法,加载驱动程序(也就是Driver接口的实现类),这些实现类都是由第三方数据库厂商提供,根据双亲委派原则,第三方类不可能被根类加载器加载

双亲委派机制源码解析?

这里forName进行加载类,forName方法的getClassLoader是获取caller对应的ClassLoader,caller就是指当前调用的forName方法的那个类,即ReflectionTest这个类,因为这个类是自己写的,所以在CLASSPATH路径下,获取到的加载器应该是应用类加载器(App ClassLoader),解析去会尝试用应用类加载器加载Persion类

通过findLoadedClass(name),去判断当前类加载器有没有加载过,没有加载过,并且parent加载器不为空,就调用parent加载器的loadClass方法…(由此递归)

当到根加载器调用loadClass方法的时候,由于根加载器没有parent,所以就执行findBootstrapClassOrNull(name)去尝试加载类,如果加载不到再让子类去加载

SPI破坏双亲委派机制- JDBC应用场景源码解析?

补充说明:Class.forName("com.ibm.db2.jcc.DB2Driver");这种写法源码里是获取的应用类加载器,这里没有问题,正常的做法。

          但是java1.6开始,后期的SPI版本是不需要写这句代码的,即不需要显示的指定驱动程序,DriverManager会自动查找合适的驱动,从而引出SPI为什么会破坏双亲委派机制。

1 假设这里按照双亲委派的加载思想,这里ServiceLoader是属于rt包,属于根加载器,根加载器去加载mysql的驱动,肯定是找不到的,而且你也没有向下去委托扩展类加载器的路,因为你起步就是根加载器,没法往下递归了,根加载器加载不到,就结束了

2 但是,SPI这里并没有这样去做,而是从Thread.currentThread().getContextClassLoader()获取类加载器,这里获取到的是应用类加载器(为什么获取到应用类加载器?下面进行了详细解释),然后由应用类加载器完成加载

 

ClassLoader构造函数

获取系统的classLoader

初始化classLoader,从Launcher中获取ClassLoader

Launcher是干嘛的?Launcher是一个启动类,Lanucher创建了扩展类加载器,创建了应用类加载器,并把扩展类加载器添加成父类,并且把应用类加载器添加到当前线程的ContextClassLoader 即Thread.currentThread().SetContextClassLoader()

但是,上图中并没有创建bootstrap加载器,为什么呢?因为bootstarp加载器是jvm内部创建,默认是所有机载器的父类。

总结:

1 SPI加载方式实际上是通过获取当前线程的应用类加载器加载的rt包的接口实现类,这些实现类是存在于CLASSPATH中

2 而双亲委派机制,是根据你当前调用forName的那类,来决定起点加载器是哪一个,再向上委派,向下加载。

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

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

相关文章

创建单链表

一、完成单链表操作,要求节点构造类型。 1、建立学生结构体(学号,姓名,成绩) 2、循环调用头插法创建整表 3、遍历单链表 4、任意位置插入一个完整的学生信息 5、任意位置删除一个学生。 6、单链表逆置 7、单链表按照学…

SpringBoot框架在文档管理中的创新应用

第3章 系统分析 3.1 需求分析 在线文档管理系统主要是为了提高工作人员的工作效率和更方便快捷的满足员工,更好存储所有数据信息及快速方便的检索功能,对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑员工的可操作性,遵循…

ELK-03-skywalking监控linux系统

文章目录 前言一、下载node_exporter二、启动node_exporter三、下载OpenTelemetry Collector四、启动OpenTelemetry Collector4.1 将配置文件下载到同级目录4.2 启动 五、查看总结 前言 skywalking安装完成后,开始我们的第一个监控-监控linux系统。 参考官方文档&a…

最古早的linux发行版,已发行30年!!

最古早的linux发行版,已发行30年!! 当谈到 Linux 发行版时,大多数人首先想到的可能是像 Ubuntu、Fedora 或 CentOS 这样的知名发行版。然而,在 Linux 的世界中,还有一款古老而稳定的发行版,它以…

SIGformer: Sign-aware Graph Transformer for Recommendation---论文学习笔记

SIGIR 2024 用于推荐的符号感知图像转换器 摘要 在推荐系统中,大多数基于图的方法主要关注用户的正面反馈,而忽视了负面反馈的价值。而将正负反馈结合起来形成符号图可以更全面地理解用户偏好。然而,现有的尝试整合这俩种类型反馈的方法很…

图片压缩工具免费怎么找?归纳了这几个压缩工具

有哪些图片压缩工具免费?在数字化时代,图像已成为我们生活中不可或缺的一部分。无论是网站设计、社交媒体分享还是文件传输,高质量的图片都扮演着重要的角色。但高质量往往意味着大文件体积,这可能会导致加载速度变慢或存储空间不…

Java基础知识扫盲

目录 Arrays.sort的底层实现 BigDecimal(double)和BigDecimal(String)有什么区别 Char可以存储一个汉字吗 Java中的Timer定时调度任务是咋实现的 Java中的序列化机制是咋实现的 Java中的注解是干嘛的 Arrays.sort的底层实现 Arrays.sort是Java中提供的对数组进行排序的…

体制内打工人收藏!5款AI写作工具,助你变成单位笔杆子~

对于初入体制内职场的新手或是日常任务繁重、难以抽身撰写文件的同事们,别再让加班的夜晚成为常态!现在,就让我揭秘几个高效公文写作宝库,它们能助你迅速掌握公文写作的精髓,海量素材信手拈来,更有快速成文…

8个高清视频素材网站,免费下载。

想要找到免费还能商用的视频素材,一定要收藏好这8个网站,高清、4K高质量,无水印,适合专业剪辑和自媒体伙伴。 1、菜鸟图库(免费商用) 视频素材下载_mp4视频大全 - 菜鸟图库 菜鸟图库网素材非常丰富&#x…

2024年AI写作工具:10款网站让你告别文章/材料创作困难!

随着AI科技的迅猛跃进,我们正步入一个前所未有的便捷时代,其广泛应用已渗透到生活的每个角落。笔者精心挑选了10款高效AI智能助手,借助这些强大工具,我们不仅能够显著提升工作效率,还能激发无限创意潜能,让…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Cloudreve云盘

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Cloudreve云盘 Cloudreve是一款开源的云存储管理系统,支持本机和第三方存储,提供用户管理、文件上传、下载、分享、在线预览等多种功能,适用于搭建个人和团队的私有云盘服务 …

【CSP】2024第二轮前的准备工作

第二轮成绩还没出,估分有希望但不高,发个帖子涨rp 1. 大纲 目前最新版本2023版NOI大纲 ,字字珠玑要细品,比如这次CSP-J第一轮就考到了格雷编码,没有经历GESP逐级洗礼的普娃哪知道这个啊。 2.在线培训 金牌教练在线…

三步教你如何让内容与众不同!

​声明:此篇为 ai123.cn 原创文章,转载请标明出处链接:https://ai123.cn/#1 在当今这个快速变化的市场中,内容的更新与维护成为了一项巨大的挑战。信息的过载导致用户对内容的“获得感”提出了更高的要求,他们不再满足…

UE5 C++: 插件编写04 | 自动增加前缀

准备工作 UObject* Asset UObject* Asset 通常指的是一个指向UObject的指针。UObject是Unreal Engine中的基类,几乎所有的引擎对象都继承自UObject。这个指针可以引用任何派生自UObject的对象,比如蓝图、材质、贴图、音频资源等资产。 如果你看到UObj…

openEuler普通用户su root时Permission denied

openEuler普通用户su root时Permission denied 背景: openEuler默认普通用户是不能通过su切换到root用户的 如果想通过su切换到root,有以下两个解决办法 1、修改/etc/pam.d/su 文件 [rootlocalhost ~]# vim /etc/pam.d/su #修改21行,将“…

微生物多样性数据的可视化技巧

在数据中穿梭找寻答案,是我们在探索微生物世界的过程中必不可少的一环。然而,单调的数据分析报告是否让你感觉枯燥乏味?这时候数据可视化的技术可就要来大展神通咯!利用图表和图形唤醒沉睡的数据,科学与艺术的搭配&…

llamafactory0.9.0微调qwen2vl

LLaMA-Factory/data/README_zh.md at main hiyouga/LLaMA-Factory GitHubEfficiently Fine-Tune 100+ LLMs in WebUI (ACL 2024) - LLaMA-Factory/data/README_zh.md at main hiyouga/LLaMA-Factoryhttps://github.com/hiyouga/LLaMA-Factory/blob/main

2.2 信道的极限容量

奈奎斯特定理 香农定理 🌏总结

Centos redis下载安装以及redis manager连接详细教程

一、redis下载以安装: 1.切换到home目录下 cd /home(/是根目录,./是当前目录 ../是父目录) 2.执行wget http://download.redis.io/releases/redis-5.0.2.tar.gz(这里,不知道为什么安装6开头的版本在make的…

增强GPT4v的Grounding能力,image-level

论文地址:arxiv.org/pdf/2310.11441 代码地址: