JVM系列-4.类加载器

  • 👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家
  • 📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理
  • 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
  • 🍂博主正在努力完成2023计划中:源码溯源,一探究竟
  • 📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀

文章目录

  • 类加载器
    • 类加载器的分类
      • Arthas中类加载器相关的功能
      • 启动类加载器
      • Java中的默认类加载器
      • 扩展类加载器
      • 应用程序类加载器
      • Arthas中类加载器相关的功能
    • 双亲委派机制
    • 打破双亲委派机制
      • 打破双亲委派机制–自定义类加载器
      • 打破双亲委派机制的第二种方法:JDBC案例
      • 打破双亲委派机制的第三种方法: OSGi模块化
        • 使用阿里arthas不停机解决线上问题
    • JDK9之后的类加载器

类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。
类加载器只参与加载过程中的字节码获取并加载到内存这一部分。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

类加载器的分类

类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。

在这里插入图片描述

类加载器的设计JDK8和8之后的版本差别较大,JDK8及之前的版本中默认的类加载器有如下几种:

在这里插入图片描述

Arthas中类加载器相关的功能

类加载器的详细信息可以通过classloader命令查看:

classloader - 查看 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResource

在这里插入图片描述

启动类加载器

在这里插入图片描述

其中最核心的就是rt.jar是jdk8中最核心的jar包,平时用到的字符串String类,装箱类型Integer,还有日期类Date等等。启动类加载器将这些都加载进来之后,相当于提供了一个基础的运行环境。

ClassLoader classLoader = String.class.getClassLoader();
System.out.println(classLoader);输出为null

但是由于这个类加载器不存在于java代码中,而是位于虚拟机环境中,所以在java环境中获取不到。所以出于安全性的考虑,在代码中,不允许我们获取到虚拟机的启动类。

制作jar的方式,idea maven install

Java中的默认类加载器

扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器。

它们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader。具备通过目录或者指定jar包将字节码文件加载到内存中。

在这里插入图片描述

扩展类加载器

在这里插入图片描述

应用程序类加载器

在这里插入图片描述

Arthas中类加载器相关的功能

类加载器的加载路径可以通过classloader –c hash值 查看:

在这里插入图片描述

双亲委派机制

由于java虚拟机中有多个类加载器,双亲委派机制的核心就是解决一个类到底是由谁加载的问题。

在这里插入图片描述

在这里插入图片描述

在Java中如何使用代码的方式去主动加载一个类呢?

方式1:使用Class.forName方法,使用当前类的类加载器去加载指定的类。

方式2:获取到类加载器,通过类加载器的loadClass方法指定某个类加载器加载。

在Idea中测试下面的案例:

在这里插入图片描述

应用程序类加载器的parent父类加载器是扩展类加载器,而扩展类加载器的parent是空。

启动类加载器使用C++编写,没有上级类加载器。

在这里插入图片描述

类加载器的继承关系可以通过classloader –t 查看:

在这里插入图片描述

如果类加载的parent为null,则会提交给启动类加载器处理。

在这里插入图片描述

如果所有的父类加载器都无法加载该类,则由当前类加载器自己尝试加载。所以看上去是自顶向下尝试加载。

在这里插入图片描述

第二次再去加载相同的类,仍然会向上进行委派,如果某个类加载器加载过就会直接返回。

在这里插入图片描述

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

在这里插入图片描述

另一个案例:com.itheima.my.C这个类在当前程序的classpath中,看看是如何加载的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

打破双亲委派机制

在这里插入图片描述

打破双亲委派机制–自定义类加载器

一个Tomcat程序中是可以运行多个Web应用的,如果这两个应用中出现了相同限定名的类,比如Servlet类,Tomcat要保证这两个类都能加载并且它们应该是不同的类。

如果不打破双亲委派机制,当应用类加载器加载Web应用1中的MyServlet之后,Web应用2中相同限定名的MyServlet类就无法被加载了。

在这里插入图片描述

Tomcat使用了自定义类加载器来实现应用之间类的隔离。

每一个应用会有一个独立的类加载器加载对应的类。

在这里插入图片描述

先来分析ClassLoader的原理,ClassLoader中包含了4个核心方法。

双亲委派机制的核心代码就位于loadClass方法中。

在这里插入图片描述

阅读双亲委派机制的核心代码,分析如何通过自定义的类加载器打破双亲委派机制。

打破双亲委派机制的核心就是将下边这一段代码重新实现。

//parent等于null说明父类加载器是启动类加载器,直接调用findBootstrapClassOrNull
//否则调用父类加载器的加载方法
if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}
//父类加载器爱莫能助,我来加载!
if (c == null) c = findClass(name);

自定义类加载器父类怎么是AppClassLoader呢?

在这里插入图片描述

以Jdk8为例,ClassLoader类中提供了构造方法设置parent的内容:

在这里插入图片描述

这个构造方法由另外一个构造方法调用,其中父类加载器由getSystemClassLoader方法设置,该方法返回的是AppClassLoader。

在这里插入图片描述

两个自定义类加载器加载相同限定名的类,不会冲突吗?

不会冲突,在同一个Java虚拟机中,只有相同类加载器+相同的类限定名
会被认为是同一个类。

在Arthas中使用sc –d 类名的方式查看具体的情况。

在这里插入图片描述

正确的去实现一个自定义类加载器的方式是重写findClass方法,这样不会破坏双亲委派机制。

在这里插入图片描述

打破双亲委派机制的第二种方法:JDBC案例

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

在这里插入图片描述

DriverManager类位于rt.jar包中,由启动类加载器加载。

在这里插入图片描述

依赖中的mysql驱动对应的类,由应用程序类加载器来加载。

在这里插入图片描述

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

在这里插入图片描述

DriverManager怎么知道jar包中要加载的驱动在哪儿?

在这里插入图片描述

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

在这里插入图片描述

SPI全称为(Service Provider Interface) 是JDK内置的一种服务提供发现机制

其工作原理:

1.在ClassPath路径下的META-INF/services文件夹下,以接口的全限定名来命名文件名,对应的文件里面写该接口的实现。

2.使用ServiceLoader加载实现类

在这里插入图片描述

SPI中是如何获取到应用程序类加载器的?

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

在这里插入图片描述

1、启动类加载器加载DriverManager。

2、在初始化DriverManager时,通过SPI机制加载jar包中的myql驱动。

3、SPI中利用了线程上下文类加载器(应用程序类加载器)去加载类并创建对象。

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

在这里插入图片描述

打破双亲委派机制的第三种方法: OSGi模块化

历史上,OSGi模块化框架。它存在同级之间的类加载器的委托加载。OSGi还使用类加载器实现了热部署的功能。

热部署指的是在服务不停止的情况下,动态地更新字节码文件到内存中。

在这里插入图片描述

使用阿里arthas不停机解决线上问题

小李的团队将代码上线之后,发现存在一个小bug,但是用户急着使用,如果重
新打包再发布需要一个多小时的时间,所以希望能使用arthas尽快的将这个问
题修复。

思路:

  • 在出问题的服务器上部署一个 arthas,并启动。
  • jad --source-only 类全限定名 > 目录/文件名.java
    jad 命令反编译,然后可以用其它编译器,比如 vim 来修改源码
  • sc -d 输入类名,找到hashcode
  • mc –c 类加载器的hashcode 目录/文件名.java -d 输出目录
    mc 命令用来编译修改过的代码
  • retransform class文件所在目录/xxx.class
    用 retransform 命令加载新的字节码

注意事项:

1、程序重启之后,字节码文件会恢复,除非将class文件放入jar包中进行更新。
2、使用retransform不能添加方法或者字段,也不能更新正在执行中的方法。

JDK9之后的类加载器

JDK8及之前的版本中,扩展类加载器和应用程序类加载器的源码位于rt.jar包中的sun.misc.Launcher.java。

在这里插入图片描述

由于JDK9引入了module的概念,类加载器在设计上发生了很多变化。

在这里插入图片描述

启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。

Java中的BootClassLoader继承自BuiltinClassLoader实现从模块中找到要加载的字节码资源文件。

启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。

在这里插入图片描述

扩展类加载器被替换成了平台类加载器(Platform Class Loader)。

(img-hsgsO33k-1705921789406)]

启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。

Java中的BootClassLoader继承自BuiltinClassLoader实现从模块中找到要加载的字节码资源文件。

启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。

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

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

相关文章

LeetCode670.最大交换

我真的怀疑他是不是难度等级评错了,因为感觉没到中级,总之先看题吧 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出:…

常用的三维尺寸公差分析软件有哪些?各有什么特点?

公差分析软件主要用于产品设计和制造过程中,帮助工程师们评估和控制产品的尺寸和公差。以下是一些常用的公差分析软件: 1.DTAS3D是一种用于三维尺寸公差分析的软件系统。 DTAS软件可以帮助工程师和设计师对零件和装配体的尺寸公差进行分析,…

静态路由实验

一:实验内容 二:实验分析 (一):实验要求 1、R6为ISP,接口IP地址均为公有地址;该设备只能配置IP地址,之后不能再对其进行其他任何配置; 2、R1-R5为局域网&#xff0c…

过滤器监听器拦截器AOP

过滤器、监听器、拦截器、AOP的实现 一、过滤器 Filter ​ 在传统的Servlet容器中,可以使用过滤器和监听器,在Java框架中还可以使用拦截器。 ​ 过滤器,这里指的是Servlet过滤器,它是在Java Servlet中定义的,能够对…

EasyExcelFactory 导入导出功能的实战使用

EasyExcelFactory 导入导出功能的实战使用分享&#xff1a; 1、jar包引入 <!-- 阿里巴巴Excel处理--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.6</version></dependen…

1、Seaborn可视化库

你的数据可视化编程初体验! Seaborn是一个基于matplotlib的图形可视化Python库,它提供了一种高级的API接口,使得制作统计图形更加容易。 Seaborn的目标是使可视化成为探索和理解数据的核心部分,它面向数据集的绘图功能对整个数据集进行操作,并在内部执行必要的语义映射和统…

Python - 【Socket】消息粘包处理demo(一)

一. 前言 在网络编程中&#xff0c;粘包是指TCP协议在传输过程中&#xff0c;多条数据被合并成一条数据发送或者一条数据被拆分成多个数据发送的现象。 二. 粘包问题的常规处理方法&#xff1a; 使用固定长度的包头 可以在发送数据前先发送一个固定长度的包头&#xff0c;包…

个人云服务器docker搭建部署前后端应用-myos

var code "87c5235c-b551-45bb-a5e4-9593cb104663" mysql、redis、nginx、java应用、前端应用部署 本文以单台云服务器为例&#xff1a; 1. 使用腾讯云服务器 阿里或其他云服务器皆可&#xff0c;类似 安装系统&#xff0c;现在服务器系统都集成安装了docker镜像&a…

[ACM学习]自上而下树形dp

问题引入 设置dp状态&#xff0c;相比于更容易出错的贪心更...不易出错。 状态设计 如果选择父结点&#xff0c;就会使孩子结点不能被选择&#xff0c;我们会多开一维的dp&#xff0c;用来标记该点是否被标记过。 以1点举例&#xff0c;f[1][0]为不选它的状态&#xff0c;那么…

FOR XML PATH 函数与同一分组下的字符串拼接

FOR XML PATH 简单介绍 FOR XML PATH 语句是将查询结果集以XML形式展现&#xff0c;通常情况下最常见的用法就是将多行的结果&#xff0c;拼接展示在同一行。 首先新建一张测试表并插入数据&#xff1a; CREATE TABLE #Test (Name varchar(70),Hobby varchar(70) );insert #T…

芯驰E3340软件编译以及更新步骤

打开已有工程File->Open Solution: 东南项目&#xff1a;e3340\boards\e3_324_ref_display\proj\jetour-t1n-fl3\sf\SES 编译&#xff1a;build->build sf 增加头文件和宏定义&#xff1a; 编译完成sf后&#xff0c;进行编译bootloader 东南项目&#xff1a;e3340\boa…

IaC基础设施即代码:Terraform 创建ACK集群 与部署应用

目录 一、实验 1.环境 2.Terraform 创建网络资源 3. 阿里云给RAM添加权限 4.Terraform 创建 ACK集群 5.在ACK集群中部署应用 6.销毁资源 二、问题 1.Terraform 验证失败 2.Terraform申请资源失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机系…

火山引擎ByteHouse:“专用向量数据库”与“数据库+向量扩展”,怎么选?

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 背景 随着LLM&#xff08;Large Language Model&#xff09;的不断发展&#xff0c;向量检索也逐渐成为关注的焦点。LLM通过处理大量的文本数据&#xff0c;获取丰…

第1章-计算机网络基础

目录 1. 计算机网络与计算机 2. 计算机网络的定义和基本功能 2.1. 定义&#xff1a;计算机网络是一组自治计算机互连的集合 2.2. 基本功能 2.3. 计算机网络的演进 2.4. 广域网(Wide Area Network&#xff0c;WAN) 2.5. 网络的拓扑结构 2.6. 数据交换方式 2.7. 衡量计算…

图灵日记之java奇妙历险记--异常包装类泛型

目录 异常概念与体系结构异常的分类异常的处理防御式编程异常的抛出异常的捕获异常声明throwstry-catch捕获并处理 自定义异常类 包装类基本数据类型及其对应包装类装箱和拆箱 泛型泛型使用类型推导 裸类型说明 泛型的编译机制泛型的上界语法 异常概念与体系结构 在java中,将程…

VisualODX——ODX数据自动转换工具 加快开发进度

在创建ODX数据库的过程中&#xff0c;我们需要录入大量的数据以及应对多种数据格式。这不仅费时费力&#xff0c;而且还需很高的人力成本&#xff0c;且其错误率也非常高&#xff0c;从而导致开发速度缓慢、效率低下。基于多年的汽车行业诊断经验&#xff0c;我们开发了VisualO…

org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException

异常信息&#xff1a; org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout 开发环境描述&#xff1a; rocketMq 版本是 4.9.0&#xff0c;部署在服务器主机上&#xff0c; Broker 部署为单节点&#xff08;单机&#xff…

jdk的安装和Tomcat的安装

jdk的安装 双击jdk&#xff0c;然后一路下一步 公共JRE可以关闭&#xff0c;没多大用&#xff0c;反而会占用内存 计算机–>属性–>高级系统设置–>环境变量 系统变量–新建 JAVA_HOMEjdk的存放路径 修改path 在path的最后面添加&#xff08;&#xff1b;%JAVA_H…

Python算法题集_移动零

本文为Python算法题集之一的代码示例 题目283&#xff1a;移动零 说明&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序 注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作 本文给出四…

ChatGPT与生成式AI在教育领域的应用前景光明,但也伴随着挑战

随着ChatGPT和其他生成式AI技术&#xff0c;如GPT-3.5、GPT-4的出现&#xff0c;我们正见证教育领域一场前所未有的变革浪潮。这些技术不仅推动了教育方式的进步&#xff0c;也为学习者带来了全新的机遇和挑战。 NO.1 教育变革的新浪潮 生成式AI技术&#xff0c;特别是ChatGPT…