【基础篇】七、线程上下文类加载器打破双亲委派机制

文章目录

  • 1、SPI机制
  • 2、JDBC案例之SPI机制
  • 3、打破双亲委派机制:线程上下文类加载器
  • 4、打破双亲委派机制:osgi模块化
  • 5、JDK9之后的类加载器
  • 6、小总结

1、SPI机制

SPI,Service Provider Interface,是JDK内置的一种服务提供发现机制。大致流程:

  • 相关组织定义好接口标准并对外提供
  • 第三方去针对接口写实现类,并将信息写在META-INF/services/${interface_name},文件内容是实现类全类名
  • 用户使用JDK提供的ServiceLoader加载(jar里的)实现类

写个小Demo直观感受下SPI,定义对外接口:

public interface SpiInterface {void helloSpi();}

其他类写实现类(这里接口和实现类放同一个jar中了,一般来说写接口和写实现的是两种角色):

public class SpiClass1 implements SpiInterface {@Overridepublic void helloSpi() {System.out.println("hello SpiClass1...");}
}
public class SpiClass2 implements SpiInterface {@Overridepublic void helloSpi() {System.out.println("hello SpiClass2...");}
}

写文件:

在这里插入图片描述

//内容
com.plat.impl.SpiClass1
com.plat.impl.SpiClass2

测试模块中引入上面的这个jar:

<dependency><groupId>com.plat</groupId><artifactId>demo</artifactId><version>0.0.1</version>
</dependency>

尝试加载:

public class SpiTest {public static void main(String[] args) {ServiceLoader<SpiInterface> serviceLoader = ServiceLoader.load(SpiInterface.class);for (SpiInterface spiClass : serviceLoader) {System.out.println(spiClass);spiClass.helloSpi();}}
}

成功获取到接口的两个实现类:

在这里插入图片描述

2、JDBC案例之SPI机制

JDBC使用DriverManager类来完成不同数据库厂商的驱动注册:

/获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testDB","root","95279527");

DriverManager位于JDK的rt.jar包,由启动类加载器去加载,而引入的第三方jar包归应用程序类加载器管。DriverManager又如何知道jar中要加载哪个驱动类?看下DriverManager类的源码,其中有一段静态代码块:

在这里插入图片描述

往下跟进loadInitialDrivers方法:

在这里插入图片描述

断点看下值,成功拿到MySQL驱动的类名:

在这里插入图片描述

即SPI机制去加载这个接口的实现类,然后用迭代器去遍历所有jar包种满足条件的类名。而MySQL驱动的jar中已按SPI流程写好了实现类和名为java.sql.Driver的文件:

在这里插入图片描述

到此,整个JDBC的流程为:

在这里插入图片描述

拿到jar包中驱动类的类名了,但这个类得靠应用程序类加载器去加载,那应用程序类加载器从哪儿来? ⇒ SPI过程能拿到应用程序类加载器,是因为SPI使用了线程上下文中保存的类加载器:

在这里插入图片描述

而线程上下文类加载器通常为应用程序类加载器(一个线程创建完之后,JVM底层会将应用程序类加载器放到线程上下文中):

//获取线程上下文类加载器
ClassLoader c = Thread.currentThread.getContextClassLoader();
//设置线程上下文的类加载器为自定义类加载器
Thread.currentThread().setContextClassLoader(new BreakClassLoader1());
//com.plat.broken.BreakClassLoader1@6537cf78
System.out.println(Thread.currentThread().getContextClassLoader());

ps:对于MySQL的驱动类,其加载过程中会自动注册驱动:

在这里插入图片描述

3、打破双亲委派机制:线程上下文类加载器

JDBC案例中,启动类加载器要委托它的下级应用程序类加载器去加载一个类,与双亲委派机制的自下而上委派不符合,因此才说打破了双亲委派机制,但其实这两块都各自满足双亲委派机制,单看DriverManager,其就应该由启动类加载器干,但看Jar中的MySQL驱动类,其也本该由应用程序类加载器干。

在这里插入图片描述

4、打破双亲委派机制:osgi模块化

历史上,OSGi模块化框架。它存在同级之间的类加载器的委托加载:
在这里插入图片描述

5、JDK9之后的类加载器

JDK8及之前的版本中,扩展类加载器和应用程序类加载器的源码位于rt.jar包中的sun.misc.Launcher.java。
在这里插入图片描述
这两个类加载器都继承自URLClassLoader,URLClassLoader是根据某一个特定的目录去找到jar包以及jar包中的字节码文件,所以,JDK8及以前,是按照jar包的位置去加载字节码文件的。JDK9引入了module的概念,之前的包放入到了jmods目录下的jmod文件中,对应的,类加载器也由原来的从jar包中加载改为了去jmod文件中加载:

在这里插入图片描述

类加载器的变化:

  • 启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中,但java代码中获取启动类加载器对象依然为null
    在这里插入图片描述

  • 扩展类加载器被替换成了平台类加载器(Platform Class Loader),平台类加载器遵循模块化方式加载字节码文件,之前扩展类加载器继承自URLClassLoader,现在继承自BuiltinClassLoader
    在这里插入图片描述

6、小总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Linux基础知识学习

开发工具&#xff1a;Xshell7VMware 首先要明确的是在Linux系统中“目录”文件夹 而所谓"家目录"指的是每个用户所拥有的一个目录&#xff0c;通常默认在 /home 目录下&#xff0c;其名称与用户的用户名相同。 ~代表的是就就是家目录 cd ~就可以直接进入当前用户下…

如何修复msvcp140_1.dll丢失问题,分享多种实测可靠的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140_1.dll丢失”的错误。msvcp140_1.dll是Microsoft Visual C 2015 Redistributable的一个组件&#xff0c;它是运行某些程序所必需的动态链接库文件。动态链接库&#xff08;DLL&…

点成案例 | 如何利用细胞计数仪在单细胞测序中评估细胞

一、概述 单细胞测序技术能够用来表征异常细胞群&#xff0c;分析稀有细胞和细胞图谱网络&#xff0c;发现异质性等。由于单细胞测序巨大的应用潜力&#xff0c;目前此技术正在经历爆炸性增长。然而&#xff0c;单细胞测序需要成本和时间的大量投资。为了确保时间和资源的投资…

【华为OD机试真题2023CD卷 JAVAJS】手机App防沉迷系统

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 手机App防沉迷系统 知识点数组字符串编程基础循环统计 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 智能手机方便了我们生活的同时,也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理的规…

Docker 概述以及整体架构

文章目录 一、Docker概述1.1 什么是 Docker1.2 Docker 如何工作1.3 底层技术 二、Docker架构2.1 Docker 整体架构2.2 Docker daemon2.3 Docker client2.4 Docker registries2.5 Docker objects2.6 Docker Desktop 参考资料 一、Docker概述 1.1 什么是 Docker Docker是一个用于…

visual studio + intel Fortran 错误解决

版本&#xff1a;VS2022 intel Fortran 2024.0.2 Package ID: w_oneAPI_2024.0.2.49896 共遇到三个问题。 1.rc.exe not found 2.kernel32.lib 无法打开 3.winres.h 无法打开 我安装时参考的教程&#xff1a;visual studio和intel oneAPI安装与编写fortran程序_visual st…

适用于 Mac 的 10 款顶级数据恢复软件分享

想要免费从Mac恢复永久删除的文件吗&#xff1f;这篇文章给你答案&#xff01; 在Mac上恢复已永久删除的文件并不难&#xff0c;只需找到合适的工具。今天&#xff0c;我们将为大家评测10款免费的Mac数据恢复软件&#xff0c;让你在拯救Mac数据时无需支付任何费用。这些软件在…

Zookeeper-Zookeeper应用场景实战

1. Zookeeper Java客户端实战 ZooKeeper应用的开发主要通过Java客户端API去连接和操作ZooKeeper集群。 可供选择的Java客户端API有&#xff1a; ZooKeeper官方的Java客户端API。 第三方的Java客户端API&#xff0c;比如Curator。 ZooKeeper官方的客户端API提供了基本的操作…

考研后SpringBoot复习1

考研后SpringBoot复习 Hello World入门 复习的版本为SpringBoot2的版本 创建maven项目 在pom文件中导入SpringBoot的依赖同时引入web开发的启动器 <!--声明springboot父项目--><parent><groupId>org.springframework.boot</groupId><artifactId>…

【12月比赛合集】22场可报名的数据挖掘大奖赛,任君挑选!

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 Kaggle&#xff08;5场比赛&#xff09;阿里天池&#xff08;…

io流——转换流

1 为什么需要转换流 为啥 乱码的原理 怎么解决&#xff1f; 1 让两边编码一样 2 使用转换流 2 转换流

ESP32入门六(读取引脚的模拟信号[3]:信号出现误差的原因[硬件篇])

在之前的文章中&#xff0c;我们介绍了ESP32在读取模拟信号时出现的误差的软件方面原因&#xff0c;在这一篇中&#xff0c;将会介绍并测试由于硬件或其它方面导致数据出现误差的原因。 一、厂商原因 首先&#xff0c;我们需要知道&#xff0c;在每块EPS32中&#xff0c;在出…