双亲委派机制

双亲委派机制简单来说就是类加载的一个顺序机制,简单来说就是:当一个类加载器收到加载请求时,检查该类是否已经被当前加载器加载过。如果已加载,直接返回;若未加载,开始委派,先委托父加载器去加载,父加载器加载不了,才自己加载。

首先介绍一下类加载器有哪几个?

1、启动类加载器:负责加载 <JAVA_HOME>/lib 目录下的核心类库(如 rt.jar、resources.jar、sun.boot.class.path 路径下的包

2、扩展类加载器:负责加载 <JAVA_HOME>/lib/ext 目录,或者由 -Djava.ext.dirs 系统变量指定路径下的所有类库。

3、应用程序类加载器:负责加载用户类路径(ClassPath)、-classpath 或 -cp 参数指定的类库

那么为什么需要双亲委派机制呢?

1、为了保证核心类库安全:如果用户自己创建一个Java.lang.String的类放在自己的项目下,那么根据双亲委派机制的加载逻辑,只有最高层级的启动类加载器才能进行加载,这样就保证了核心类的安全性

**2、 避免类重复加载:**从最底层的应用程序类加载器开始检查一直到最上层的类加载器,只要检查到这个类已经被加载了,那么就会直接返回确保了类只加载一次

3、保证类的唯一性: 类身份 = (全限定名, 定义类加载器),同一个类名,最终由同一个定义类加载器加载,得到同一个 Class 对象

那么有些场景为什么要打破双亲委派机制?如何打破双亲委派机制?

1、Tomcat启动多个应用

我们知道Tomcat可以启动多个应用,每个应用可能会出现多个spring依赖的版本,那么不同的spring版本依赖的名称肯定是相同的,那么根据双亲委派机制,就会把相同的名称的依赖包下的类只加载一次,这样就会出现版本不一致的情况

那么如何解决呢?

修改ClassLoader 并重写 loadClass 方法

1、设计每个应用都有独立的应用程序类加载器

2、BootstrapClassLoader 尝试去加载(仅针对 java.* 等核心包做安全隔离)。

WebAppClassLoader 优先尝试去加载(直接去 WEB-INF/classes 和 WEB-INF/lib 找)。

System/CommonClassLoader 最后才尝试去加载(如果本地 WEB-INF 找不

2、JDBC

DriverManager 位于 java.sql 包,由启动类加载器 Bootstrap ClassLoader 加载。DriverManager 需要加载 MySQL 的 com.mysql.cj.jdbc.Driver,这个类在 CLASSPATH 下,Bootstrap 加载不了。

那么如何解决呢?

SPI 与线程上下文类加载器

核心库的加载器无法向下识别第三方驱动,于是引入 Thread.currentThread().getContextClassLoader(),让父加载器逆向请求子加载器去加载驱动实现。上下文类加载器就是应用程序类加载器,这样就能够将驱动类正常加载

总结:

想要打破双亲委派机制有两种方式:

1、自定义ClassLoader 并重写 loadClass 方法

2、改变加载顺序,如:调用上下文类加载器

最后附上一个表格关于是否重写对应的类加载器的方法

方法 职责 是否可重写
loadClass 双亲委派逻辑 可重写,但不推荐
findClass 读取字节流,定义类 推荐重写
defineClass 把字节流变成 Class 对象 final,不可重写
findLoadedClass 检查是否已加载 final
resolveClass 触发链接 final
相关推荐
runningshark1 小时前
数据结构-第二章-线性表及其顺序存储
数据结构
65岁退休Coder1 小时前
把 Agent 框架拆开:PI 开发生产级 Harness
后端·node.js·agent
步行cgn1 小时前
Spring Bean 的生命周期详解
java·后端·spring
ps酷教程1 小时前
数据权限DataPersmission
java·学习
郝学胜-神的一滴1 小时前
C++20模板元编程 04:变量模板 别名模板与模板Lambda实战
服务器·开发语言·数据结构·c++·程序人生
驭渊的小故事1 小时前
Java 项目-jckson序列化工具
java·开发语言
君顾11 小时前
上海24小时自助健身房系统开发实战指南:从架构设计到功能实现
java·开发语言·健身房
爱勇宝2 小时前
用了一个月 WorkBuddy,聊聊我的真实感受
前端·后端·程序员
用户3721574261352 小时前
Java 拆分 Word 文档教程:按页、分页符和分节符拆分
java