锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 默认分类
  3. 五个经典的破坏双亲委派场景,Java被啪啪打脸

五个经典的破坏双亲委派场景,Java被啪啪打脸

0
  • 默认分类
  • 发布于 2024-09-24
  • 12 次阅读
黄健
黄健

在《深入理解Java类加载机制,再也不用死记硬背了》这篇文章中提到,从JVM的角度看,加载的读取二进制流和初始化阶段,是开放了主导权给用户的。而剩下的所有部分都是JVM内部完成的。


那为什么要这样做呢?这是符合面向对象中的开闭原则和封装思想的设计。JVM将类加载内部复杂的实现封装了起来,拒绝开发者修改。只提供了一个拓展接口,用于二进制流的读取。

流程上搞懂了,那JVM是怎样使用代码来实现这些步骤的呢?这就要聊到Java的类加载器了。

类加载器

类加载器的分类是Java规范,属于抽象的概念。规范将类加载器分成启动类和非启动类两大类。

HotSpot对类加载器实现有以下分类(以下描述中省略了HotSpot定语):

启动类加载器是C/C++语言实现的,无法作为对象被程序引用。主要用来加载Java的核心类库。类库主要由Java启动参数指定,默认是${JAVA_HOME}/lib。HotSpot还会对类名进行白名单校验来提高安全性。

非启动类加载器都是使用Java来实现,继承自java.lang.ClassLoader,可以作为类对象被程序引用。它也分成3种,简单说一下区别。

扩展类加载器ExtensionClassLoader加载的是${JAVA_HOME}/lib/ext下或者启动时指定的类库。它目标是加载Java类库的扩展,是标准类库的补充。

应用类加载器ApplicationClassLoader加载的是环境变量classpath指定的类库。咱们平时使用maven的话,就是使用maven加载的类库和自己编写的代码。

用户类加载器就是用户自己定义的类加载器,也叫自定义类加载器。只要继承于应用类加载器即可。定义不同的类加载器会使用不同的命名空间。因为不同的命名空间是个隐含的限定名区分,是不同的对象。


双亲委派模型

双亲委派的目标是在默认情况下,一个限定名的类只会被一个类加载器加载并解析使用,这样在程序中,它就是唯一的,不会产生歧义。

在被动的情况下,当一个类加载器收到类加载请求,它不会首先自己去加载。而是传递给父加载器。这样,所有的类首先都会先由最上层的启动类加载器进行加载,只有父加载器无法完成类加载才会由子加载器完成。


白话来说:双亲委派模型中,如果类A调用了类B,那类B可能是类A在使用过程中被动加载进来的。那如果类A是用应用程序类加载器加载的,那么类B只能由应用程序类加载器或其父类或者上一层父类来加载。不能由自定义类加载器来来加载。

双亲委派模型并不是一个拥有强约束力的模型。它存在设计缺陷,在一些情况下可以被主动破坏。


五种经典的破坏双亲委派场景


第一次破坏


在《深入理解Java虚拟机》这本书中,记录了怎样破坏双亲委派:因为双亲委派机制原则在java.lang.ClassLoader的loadClass方法中。只要重写loadClass方法就可以破坏。书中还写了一个重写loadClass方法来进行破坏的小样例,这个小样例被称为双亲委派的第一次破坏。


Tomcat场景

这个破坏的样例有没有什么实际价值意义呢?还真有,后来Tomcat就使用这种方式对双亲委派进行破坏,来达到使用一个web容器部署两个或者多个应用程序,不同的应用程序,可能会依赖同一个第三方类库的不同版本,还要能保证每一个应用程序的类库都是独立、相互隔离的效果。


tomcat自定义了类加载器,重写loadClass方法使其优先加载自己目录下的class文件,来达到class私有的效果。不过咱们现在流行使用的都是嵌入式的web容器了,将来更多的场景还是一个应用程序使用一个单独的web容器。所以这种破坏双亲委派的价值在降低。


基于SPI的三种经典破坏场景


还有一种java特性叫做SPI,在《JAVA SPI(Service Provider Interface)原理、设计及源码解析》里,我不仅说了什么是SPI,还提到了三种经典场景都在使用,它们分别是jdbc、Dubbo、Eleasticsearch。没错,这三种经典场景通过SPI都使得双亲委派遭到破坏。下面以jdbc为例做说明。

jdbc驱动Driver在十几年前,我还手写过用DriverManager来加载的代码。

Class.forName("com.mysql.cj.jdbc.Driver");

Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");

DriverManager初始化时是这样的,注意红框内容。

红框内容翻译一下就是说:由启动类加载器加载的DriverManager初始化时要去加载Driver驱动。

jdbc驱动由Serverloader.load加载。


而Serverloader.load里优先使用当前线程的类加载器而不是自身使用的类加载器来加载Driver。当前线程是使用方要么是应用类加载器要么是自定义类加载器,总归类A调用类B,B没有使用父类而使用了子类加载器,所以破坏了双亲委派。


双亲委派被破坏的补救措施


那朋友就问了,java.lang.ClassLoader把loadClass方法定义为final是不是就解决了双亲委派被破坏的问题呢?java.lang.ClassLoader的loadClass方法在Java很早的版本就有了,而双亲委派模型是在JDK1.2中引入的。Java是向下兼容的,所以不是不想改而是改不了了。一个补救措施是推荐使用findClass方法而不是直接重写loadClass。当然了,如果有人登录了服务器,把JDK文件给替换了,也就失效了。这个不在讨论范围。

原文链接:https://mp.weixin.qq.com/s/cRBWC9aiEHnwEwYOISTfLQ

标签: #知识库 257
相关文章
最全的办公楼智能化解决方案

最全的办公楼智能化解决方案 2024-10-16 08:40

办公楼综合体智能化如何建设?有哪些系统?近几年,办公楼智能化的项目越来越多,不少项目经理都参与其它,同事办公楼综合体也是弱电系统涉及的最多的项目之一,本期我们一起来看下,最全的办公楼项目智能化设计方案。

规范标准查询、下载网站 2024-10-12 16:41

我们在工作中经常需要用到各种各样的规范标准,这里给大家介绍一些免费查询和下载规范的网站,个人亲测可用。 标准查找查新网站 工标网: http://www.csres.com/ 中国国家标准化管理委员会:http://openstd.samr.gov.cn/bzgk/gb/index 全国标准信息公共

【计算机网络】网络层协议解析 2024-10-08 11:24

网络层的两种服务 IPv4 * 分类编址 划分子网 无分类地址 IPv4地址应用 IP数据报的发送和转发过程 * 主机发送IP数据报 路由器转发IP数据报 IPv4数据报首部格式 ICMP网际控制报文协议 虚拟专用网VPN与

FFmpeg教程(超级详细版) 2024-10-08 11:24

一、参考资料 通过ffmpeg把图片转换成视频 FFmpeg命令(一)、使用filter_complex命令拼接视频 FFmpeg 视频处理入门教程给新手的 20 多个 FFmpeg 命令示例 FFmpeg命令行转码

计算机网络:物理层 —— 数据的传输方式 2024-10-08 11:24

文章目录 * 传输方式 * 串行传输 * 串行传输方式 特点 应用 并行传输 * 特点 应用 网卡的串/并转换 同步传输 * 同步时钟频率的误差问题 特点 应用<

授权码机制 V2.1 2024-10-07 10:26

大家好,我是机灵鹤。 根据读者朋友们反馈的问题和建议,对 授权码 V2.0 版本做了一些优化。 优化内容主要解决了以下几个问题: 优化了授权机制中的时间校验逻辑,避免用户通过回调本地时间来绕过授权机制的问题。 封装和简化了授权接口,开发者可以更方便地接入到自己的程序中。

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.