双亲委派机制和SPI的理解

双亲委派机制和SPI的理解

双亲委派机制基本原理

双亲委派机制简单的来说是JVM类加载过程的一个非强约束模型。子类加载器加载对应的Class,不会直接加载,首先会交由其父类加载器加载,若父类加载器无法加载,则由自己加载。

Java一共有三层类加载器,级别从上往下依次是:

  • BootStrap Class Loader:该类加载器由C++实现,在java语言中无法感知,所以在获取类加载器为null,主要用于加载<JAVA_HOME>\lib 目录下的类。当然也可自己通过JVM参数指定。

  • ExtClassLoader:扩展类加载器,主要用于加载<JAVA_HOME>\lib\ext 目录下的类。

  • AppClassLoader:系统类加载器,用大白话来讲,就是加载我们自己定义的类的类加载器还有引入的一些第三方jar包。

    具体的示例代码如下:

    System.out.println(HashMap.class.getClassLoader()); // null
    System.out.println(JarFileSystemProvider.class.getClassLoader()); //sun.misc.Launcher$ExtClassLoader@355da254
    System.out.println(Main.class.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2
    

双亲委派机制的具体实现可以参考ClassLoader#loderClass方法,具体代码如下:

protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// 先从父加载器加载if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}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 statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

不难发现,在Jdk源码中,类加载器自身加载类的方法其实findClass,因此官方推荐自定义类加载器的时候,建议重载findClass,而不是loadClass方法,因为lodaClass方法重载后,若开发者没有按照规范开发,便会打破双亲委派机制。

双亲委派机制存在意义

  • 有序性】首先,双亲委派机制能够有效的避免一个类被重复加载,一个类只会被加载一次。若一个类被父类加载器加载,对于子类加载器其实是无感的,若子类加载器直接加载对应的class,会导致一个类被重复加载。

  • 安全性】同样也是处于安全性考虑,如果JDK和核心类库,被其他类加载器加载,Java中最基础的行为也就无法保证。在双亲委派的场景下,能够确保被BootStrap类加载器加载,就不会出现上述问题。

双亲委派的破坏

  • 通过自定义类加载器,重写loadClass来破坏双委派。

  • JNDI (Java Naming and Directory Interface,Java命名和目录接口) 需要服务者提供接口实现代码(SPI)。这里一个典型的应用就是JDBC的Driver驱动实现,各个数据库厂商可以针对JavaEE中的规范自行实现。这里主注意的是只有Java类库中的SPI才会对双亲委派进行破坏,自定义接口和第三方Jar包并不会对双亲委派机制进行破坏。以Driver的SPI为例,参考ServiceLodar#nextService

    破坏双亲委派的代码就是Class.forName(cn, false, loader) 这一行。

    传入的是一个loader,默认是系统类加载器。

     private S nextService() {if (!hasNextService())throw new NoSuchElementException();String cn = nextName;nextName = null;Class<?> c = null;try {// 双亲委派被破坏c = Class.forName(cn, false, loader);} catch (ClassNotFoundException x) {fail(service,"Provider " + cn + " not found");}if (!service.isAssignableFrom(c)) {fail(service,"Provider " + cn  + " not a subtype");}try {S p = service.cast(c.newInstance());providers.put(cn, p);return p;} catch (Throwable x) {fail(service,"Provider " + cn + " could not be instantiated",x);}throw new Error();          // This cannot happen}
    

    如果直接写出Class.forName(cn),那他的加载器就是ServiceLoader的类加载器,而ServiceLoader位于<JAVA_HOME>\lib,它的类加载器是BootStrap类加载器,显然无法加载第三方jar包及其用户自定义代码,需要指定子类加载器,BooStrap类加载器将类加载委托给AppClassLodaer。因此就造成双亲委派被破坏。

  • 不难发现,由于双亲委派机制的存在,一个类至始至终只会被加载一次,因此当程序需要热更新时,双亲委派机制也就随之被破坏。

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

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

相关文章

Simple WPF: WPF 自定义按钮外形

WPF的按钮提供了Template模板,可以通过修改Template模板中的内容对按钮的样式进行自定义。结合资源字典,可以将自定义资源在xaml窗口、自定义控件或者整个App当中调用最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。 WPF的按钮提供了Template模板,可以…

三维重建工作的一些调研

GPT关于3D-GS的回答如果我获得了一个3D高斯溅射的表达,给定任意的相机内参和外参,是不是就能生成一副2D图像Yes, given a 3D Gaussian splatting representation and the intrinsic and extrinsic camera parameters, you can generate a 2D image from any desired viewpoin…

Spark Special_杨宁远 杂题分析.md

Spark Special 图论_杨宁远 杂题分析 Date: 2024-07-03 Preface 本文基于杨宁远 @ynycoding 的课件与题单,对省选/NOIP阶段图论的建模方法和解题策略进行总结,以及本阶段常用方法、模型和 Trick。 A. [AGC056C] 0/1 Balanced [AGC056C] 01 Balanced - 洛谷 | 计算机科学教育新…

按指定日期重复

问题:根据D1指定的日期将A2:C8区域进行重复公式1(姓名)右拉下拉完成 =INDEX(A:A,MOD(ROW(A1)+COUNTA(A:A)-2,COUNTA(A:A)-1)+2) 公式2(日期)下拉完成 =SUBSTITUTE(LEFT(D$1,FIND("-",D$1)-1),".","/")+(ROW(A1)-1)/(COUNTA(A:A)-1) 公式3(…

语法2-运算符、包机制、JavaDoc

语法 运算符 运算符具有优先级-网上查(一般使用括号保证)/-除,%-取余符号-21/10二十一除十取余数,幂运算使用工具类表示Math.pow(2,3)-2的3次方 ++自加,--自减 int a =3 ; int b =a++;//输出a=4,b=3 int b =++a;//输出a=4,b=4==-等于,!=-instanceof-不等于逻辑运算符-与或…

厦门福州七日游

厦门福州七日游2024-06-30 上午被发短信告知航班延误两个半小时。 晚上八点多九点才到了厦门,湘妹 yhp yzf 已经在酒店了。厦门机场不通地铁?????于是打了个车去地铁站。 酒店就在中山路步行街上,有各种店铺。点了一份外卖,和大伙打了一会三国杀,输了几局 2024-07-01 …

SumIf的问题

问题:进销存表数据等于同货号入库表中数据 函数公式解决:=SUMIF(入库!A:A,B3,入库!C:C)

7/8死神永生服周报第七期

1. 死神永生新闻 2. 死神永生服TNT军事基地[三] 3. 死神永生服的古代建筑之自然选择号目录死神永生新闻 死神永生服TNT军事基地[三] 死神永生服的古代建筑之自然选择号这几天又没上死神永生,主要是期末比较繁忙,因此又停了一期。。真的很抱歉。死神永生新闻前一周的治理新闻时…

两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码

今天推荐两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码,这两个源码完整,都是基于thinkphp内核开发的,框架稳定,带数据库,源码文件,可以直接部署使用。第一个:3D模型 图纸模型 机械模型(图纸)下载资源网站源码 thinkphp5开发原创模型(图…

win 10 使用SSH 连接

本教程建议使用win 10 、win 11 非家庭版使用 首先安装 ssh 服务端 Get-Service -Name *ssh* #查看服务ssh -V #查看ssh 版本 netstat -an |findstr :22 # 查看端口是否被监听 ipconfig # 查看本机IP ssh administrator@IP 在用户/.ssh 目录下创建文件 authorized_keys 将…

音视频录制与播放原理

图片来源于网上学习资料,零声学院!

2.基于Containerd运行时搭建Kubernetes多控制平面集群实践-腾讯云开发者社区-腾讯云

https://cloud.tencent.com/developer/article/21298462.基于Containerd运行时搭建Kubernetes多控制平面集群实践发布于 2022-09-29 19:27:531K0 举报文章被收录于专栏:全栈工程师修炼之路[TOC]0x00 前言简述 本章主要讲述,如果使用kubeadm进行安装配置K8S集群,并指定使用co…