JVM 类加载器 详解

类加载器

两个类来源于同一个 Class文件,被同一个Java虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等

这里所指的“相等”,包括代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括了使用instanceof关键字做对象所属关系判定等各种情况

总结:

类加载器

​ 类加载器作用于类加载的加载阶段,也就是加载class文件到方法区中,并且在方法区生成Class对象,通过Class对象可以访问方法区中的类信息。每个Class对象都有一个引用指向加载它的类加载器。

​ JVM中内置了三个类加载器,启动类加载器、扩展类加载器、应用程序类加载器。其中,启动类加载器用来加载JAVA_HOME/lib下的核心类库比如rt.jar;扩展类加载器用来加载JAVA_HOME/lib/ext下的类;应用程序类加载器用来加载classpath下的类。

​ 这三个类加载器都继承自ClassLoad抽象类,类加载器可以通过getParent()方法来获取它的父加载器,例如应用程序类加载器的父加载器是扩展类加载器,而扩展类加载器的父加载器是启动类加载器,只不过扩展类加载器通过getParent()方法获得的是null,因为启动类加载器是基于c++实现的。

​ 三个加载器的父子关系不是通过继承来实现的,而是通过组合方式来实现的。

双亲委派模型:

  • 启动类加载器(Bootstrap Class Loader):是由Hotspot虚拟机提供的类加载器,JDK9之前使用C++编写的、JDK9之后使用Java编写。默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等。
  • 扩展类加载器(Extension Class Loader):默认加载Java安装目录/jre/lib/ext下的类文件。(JDK9及以后,被重命名为平台类加载器Platform ClassLoader)
  • 应用程序类加载器(Application Class Loader):负责加载用户类路径(ClassPath)上所有的类库

双亲委派机制指的是:自底向上查找是否加载过,再由顶向下进行加载

​ 双亲委派模型:除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。不过这里类加载器之间的父子关系一般不是以继承(Inheritance)的关系来实现的,而是通常使用组合 (Composition)关系来复用父加载器的代码。

在这里插入图片描述

​ 如果一个类加载器收到了类加载的请求,每个类加载器都会先检查是否已经加载了该类,如果已经加载则直接返回,否则会将加载请求委派给父类加载器。每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时, 子加载器才会尝试自己去完成加载。

为什么使用双亲委派:

​ 1.保证类加载的安全性,通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。

​ 2.避免重复加载,双亲委派机制可以避免同一个类被多次加载。

为什么要向上委派,不能向下委派?

​ 是否能一开始就由启动类加载器加载所有的类,启动类加载器发现不在自己加载范围内的类就交给自己的子类加载器?答案是不行的,因为一个类加载器可以只有一个父类加载器,需要加载类时直接向上委派就行,但如果是向下委派,同时又有多个子类加载器,这时候就不知道要委派给哪个子类加载器的(可能有多个子类加载器的原因是因为可以有自定义类加载器,加载器的组合是多样的,但不管怎样,只可能有一个父类加载器),这就好比一个二叉树,从叶子节点向上走,是有且只有一条唯一的路径的,而且这条路径的终点必然是根节点,而从根节点出发,一直向下走,是不能确定一条唯一路径的,虽然最终能到达某一叶子节点,但具体是哪个叶子节点取决于每次向下走的路线决策。而且向下委派意味着需要修改应用程序类加载器的源码。
在这里插入图片描述

破坏双亲委派模型:

在这里插入图片描述

自定义加载器的话,需要继承 ClassLoader 。如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 loadClass() 方法。

Tomcat采用自定义类加载器破坏了双亲委派,实现了Web应用之间的类的隔离
在这里插入图片描述
在这里插入图片描述

JDBC:

​ JDBC中使用了DriverManager来管理项目中引入的不同数据库的驱动,比如mysql驱动、oracle驱动。

DriverManager属于rt.jar是启动类加载器加载的。而用户jar包中的驱动需要由应用类加载器加载,这就违反了双亲委派机制。

​ DriverManage使用SPI机制,最终加载jar包中对应的驱动类。

​ SPI中使用了线程上下文中保存的类加载器进行类的加载,这个类加载器一般是应用程序类加载器。

这种由启动类加载器加载的类,委派应用程序类加载器去加载类的方式,打破了双亲委派机制。

​ JDBC接口是jre下的,但实现是第三方供应商提供的,按理来说,一个类及其依赖类由同一个类加载器加载(确保这些类之间的依赖关系正确并保持一致),但这种情况下不会被同一个类加载器加载,这就需要用到线程上下文类加载器解决

​ 线程上下文类加载器:当一个线程启动时,jvm会将应用类加载器赋值给当前线程的线程上下文类加载器,此时父类加载器就可以提高线程上下文类加载器获取到子类加载器,再由子类加载器加载父类找不到的类

在这里插入图片描述

什么时候需要自定义类加载器:

  • 想加载非classpath随意路径的类文件
  • 隔离同名类,需要不同应用下的同名类可以不冲突,如tomcat容器

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

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

相关文章

Javascript 编程基础(5)面向对象 | 5.1、构造函数实例化对象

文章目录 一、构造函数实例化对象1、基本语法2、构造函数与原型的关系3、完整的原型链4、构造函数的特点5、prototype与__proto__属性5.1、对象实例的__proto__属性5.2、prototype属性仅存在于函数对象5.3、实例与原型的关系5.4、获取对象原型 6、注意事项 前言: 在…

自动驾驶科普(百度Apollo)学习笔记

1. 写在前面 在过去的几年里,自动驾驶技术取得飞速发展,人类社会正逐渐走向一个新时代,这个时代中,汽车不仅仅是一个交通工具,更是一个智能的、能够感知环境、做出决策并自主导航的机器伙伴。现在正好也从事这块的工作…

Windows应用-音视频捕获

下载“Windows应用-音视频捕获”项目 本应用可以同时捕获4个视频源和4个音频源,可以监视视频源图像,监听音频源;可以将视频源图像写入MP4文件,将音频源写入MP3或WAV文件;还可以录制系统播放的声音。本应用使用MFC对话框…

MATLAB生成大规模无线通信网络拓扑(任意节点数量)

功能: 生成任意节点数量的网络拓扑,符合现实世界节点空间分布和连接规律 效果: 30节点: 100节点: 500节点: 程序: %创建时间:2025年6月8日 %zhouzhichao %自然生长出n节点的网络% …

TDengine 开发指南—— UDF函数

UDF 简介 在某些应用场景中,应用逻辑需要的查询功能无法直接使用内置函数来实现,TDengine 允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后,可以像系统内置函数一…

C#提取CAN ASC文件时间戳:实现与性能优化

C#提取CAN ASC文件时间戳:实现与性能优化 在汽车电子和工业控制领域,CAN总线是最常用的通信协议之一。而ASC(ASCII)文件作为CAN总线数据的标准日志格式,广泛应用于数据记录和分析场景。本文将深入探讨如何高效地从CAN…

计算机网络基础总结:TCP/IP 模型、TCP vs UDP、DNS 查询过程

在学习计算机网络的过程中,理解 TCP/IP 模型与 OSI 模型的对应关系、掌握 TCP 与 UDP 的区别,以及熟悉 DNS 的查询过程,是打好网络基础的关键。本文将围绕这三部分进行简明扼要的讲解。 一、TCP/IP 模型与 OSI 七层模型的对应关系 1. OSI 七…

基于PHP的扎染文创产品商城

有需要请加文章底部Q哦 可远程调试 基于PHP的扎染文创产品商城 一 介绍 扎染文创产品商城系统基于原生PHP开发,数据库mysql,前端bootstrap,jquery.js等。系统角色分为用户和管理员。 技术栈:phpmysqlbootstrapphpstudyvscode 二…

数据库学习(三)——MySQL锁

一、MySQL锁 当多个用户或进程并发操作数据库时,为了避免数据冲突、脏读、不可重复读、幻读等问题,数据库通过锁机制来保证数据的一致性和完整性。 MySQL 锁的总体分类: 分类维度类型说明按作用对象表级锁(Table Lock&#xff…

<3>-MySQL表的操作

目录 一,创建表 二,查看表结构 三,修改表 四,删除表 一,创建表 语法: CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 eng…

【OSG学习笔记】Day 15: 路径动画与相机漫游

本章来学习下漫游相机。 路径动画与相机漫游 本届内容比较简单,其实就是实现物体的运动和相机的运动 当然这两个要一起执行。 贝塞尔曲线 贝塞尔曲线(Bzier curve)是一种在计算机图形学、动画制作、工业设计等领域广泛应用的参数曲线&am…

LabVIEW自感现象远程实验平台

LabVIEW开发自感现象远程实验平台,通过整合 NI数据采集设备、菲尼克斯(Phoenix Contact)继电器模块及罗技(Logitech)高清摄像头,实现远程数据采集、仪器控制与实时监控三大核心功能。平台突破传统实验装置局…

数据结构——F/图

一、图的基本概念 图是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E)&#xff0c;其中&#xff1a; 顶点集合V {x|x属于某个数据对象集}是有穷非空集合&#xff1b; E {(x,y)|x,y属于V}或者E {<x, y>|x,y属于V && Path(x, y)…

springcloud openfeign 偶现 Caused by: java.net.UnknownHostException

背景 最近查看日志发现某服务偶现Caused by: java.net.UnknownHostException 同时查看eureka的access.log 出现如下异常 10.xxx.xxx.xxx - - [27/May/2025:23:57:29 0800] “PUT /eureka/apps/{appName}/{host}:xxx-job:8082?statusUP&lastDirtyTimestamp1748351637173 H…

第12篇:数据库中间件日志设计与追踪系统落地实践

12.1 引言&#xff1a;中间件日志系统为何如此关键&#xff1f; 数据库中间件作为连接前端应用与后端数据库的“网关”&#xff0c;承载着路由、负载均衡、SQL 改写、权限控制等复杂逻辑。 在出现 性能问题、故障排查、安全审计 等场景中&#xff0c;若没有完善的日志体系&am…

OpenAI对抗法庭命令:捍卫ChatGPT用户隐私之战

人工智能公司OpenAI近期正积极对抗一项涉及隐私问题的法庭命令。该命令要求OpenAI保留所有ChatGPT用户日志&#xff0c;包括已删除的对话记录以及通过API调用生成的聊天内容。 命令背后的真实动机 值得注意的是&#xff0c;法院发布这一指令并非出于对用户隐私或内容安全的考…

嵌入式学习--江协stm32day5

USART 1. 引脚与接口层 异步引脚&#xff1a; TX&#xff1a;发送数据输出&#xff1b;RX&#xff1a;接收数据输入&#xff1b;SW_RX&#xff1a;单线半双工模式的接收引脚&#xff08;替代 RX&#xff09;。 同步引脚&#xff1a;SCLK&#xff1a;同步模式下的时钟输出&…

使用Fiddler抓包

有时候需要跟踪一些小程序的HTTP请求&#xff0c;但是无法像浏览器一样F12查看请求&#xff0c;因此需要借助其他的工具进行&#xff0c;在这里推荐使用Fiddler 配置 此时检查系统代理已经变成如下配置&#xff1a; 抓包 此时随便打开一个小程序&#xff0c;就可以进行抓包…

python学习打卡day47

DAY 47 注意力热图可视化 昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 # 可视化空间注意力热力图&#xff08;显示模型关注的图像区域&#xff09; def visualize_attention_map(model, test_loader,…

MySQL-运维篇

运维篇 日志 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&am…