【JVM基础篇】类加载器分类介绍

文章目录

    • 类加载器
      • 什么是类加载器
      • 类加载器的作用是什么
      • 应用场景
      • 类加载器的分类
        • 启动类加载器
          • 用户扩展基础jar包
        • 扩展类加载器和应用程序类加载器
        • 扩展类加载器
          • 通过扩展类加载器去加载用户jar包:
        • 应用程序加载器
      • Arthas中类加载器相关功能
    • 文章说明

类加载器

什么是类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术

在这里插入图片描述

在这里插入图片描述

类加载器会通过二进制流的方式获取到字节码文件的内容,接下来将获取到的数据交给Java虚拟机,虚拟机会在方法区和堆上生成对应的对象保存字节码信息。

类加载器的作用是什么

  • **类加载器(ClassLoader)负责在类加载过程中的字节码获取并加载到内存这一部分,**通过加载字节码数据放入内存转换成byte[],接下来调用虚拟机底层方法将byte[]转换成方法区和堆中的数据。

应用场景

  • 企业级应用
    • SPI机制
    • 类的热部署
    • Tomcat类的隔离
  • 大量的面试题
    • 什么是类的双亲委派机制
    • 打破类的双亲委派机制
    • 自定义类加载器
  • 解决线上问题
    • 使用Arthas不停机解决线上故障

类加载器的分类

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

  • 虚拟机底层实现:源代码位于Java虚拟机的源码中,实现语言与虚拟机底层语言一致,比如Hotspot使用C++。主要目的是保证Java程序运行的基础类被正确地加载,比如java.lang.String,Java虚拟机需要确保其可靠性。
  • JDK中默认提供或者自定义:JDK中默认提供了多种处理不同渠道的类加载器,程序员也可以自己根据需求使用Java语言定制。所有Java中实现的类加载器都需要继承ClassLoader这个抽象类。

在这里插入图片描述

可以查看所有类加载器,即ClassLoader的子类

在这里插入图片描述

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

  • 启动类加载器(Bootstrap ClassLoader、C++实现):加载核心类,String类
  • 扩展类加载器(Extension ClassLoader、Java实现):加载扩展类,拓展Java中比较通用的类,只是通用,不是特别重要,最重要的在启动类加载器加载了
  • 应用程序类加载器(Application ClassLoader、Java实现):加载应用classpath中的类,包括我们自己写的类,还有第三方Jar包的类
  • 自定义类加载器(Java实现):需要重写findClass方法。

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

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

在这里插入图片描述

  • BootstrapClassLoader是启动类加载器,numberOfInstances是类加载器的数量只有1个,loadedCountTotal是加载器所加载的类的数量为1861个
  • ExtClassLoader是扩展类加载器
  • AppClassLoader是应用程序类加载器
  • DelegatingClassLoader是用来提升反射效率的类加载器
  1. 启动类加载器
  • 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器,Java程序员无法修改或者扩展源代码,所以只关注这个加载器的作用。
  • 作用:默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等,给java程序提供了一个基础的运行环境。

在这里插入图片描述

运行如下代码:

/*** 启动程序类加载器案例*/
public class BootstrapClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = String.class.getClassLoader();System.out.println(classLoader);System.in.read();}
}

这段代码通过String类获取到它的类加载器并且打印,本来以为是Bootstrap ClassLoader,结果是null。这是因为启动类加载器在JDK8中是由C++语言来编写的,在Java代码中去获取既不适合也不安全,所以才返回null

在Arthas中可以通过sc -d 类名的方式查看加载这个类的类加载器详细的信息,比如:

在这里插入图片描述

通过上图可以看到,java.lang.String类的类加载器是空的,Hash值也是null。所以只要看到为null,就知道这是启动类加载器

用户扩展基础jar包

如果用户想扩展一些比较基础的jar包,让启动类加载器加载,有两种途径:

  • 打包成jar包,放入jre/lib下进行扩展。不推荐,尽可能不要去更改JDK安装目录中的内容,因为即使放进去由于文件名不匹配的问题也不会正常地被加载(在加载jar包的时候,会对名称进行校验,名称必须符合JVM内部的一些规范)。
  • **使用参数进行扩展。**推荐,使用-Xbootclasspath/a:jar包目录/jar包名进行扩展,参数中的/a代表新增。

【使用参数进行扩展实现流程】

先创建第一个项目,打包成jar包

在这里插入图片描述

再创建第二个项目,在第二个项目的IDEA配置中添加虚拟机参数,就可以加载D:/jvm/jar/classloader-test.jar这个jar包了。

在这里插入图片描述

使用Class.forName获取Jar包的类,可以正常执行初始化,说明自己拓展的Jar包被加载了

在这里插入图片描述

扩展类加载器和应用程序类加载器
  • 扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器。
  • 它们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader,具备通过目录或者指定jar包将字节码文件加载到内存中的能力。

继承关系图如下:

在这里插入图片描述

  • ClassLoader类:定义了具体的行为模式,简单来说就是先从本地或者网络获得字节码信息,然后调用虚拟机底层的方法创建方法区和堆上的对象。这样的好处就是让子类只需要去实现如何获取字节码信息这部分代码
  • SecureClassLoader:提供了证书机制,提升了安全性。
  • URLClassLoader:提供了根据URL获取目录下或者指定jar包进行加载,获取字节码的数据的能力。

扩展类加载器和应用程序类加载器继承自URLClassLoader,获得了上述的三种能力。

  1. 扩展类加载器

扩展类加载器(Extension Class Loader)是JDK中提供的、使用Java编写的类加载器。默认加载Java安装目录/jre/lib/ext下的类文件。

在这里插入图片描述

如下代码会打印ScriptEnvironment类的类加载器。ScriptEnvironment是nashorn框架中用来运行javascript语言代码的环境类,他位于nashorn.jar包中被扩展类加载器加载。这些类我们很少用,所以被放到了扩展类加载器中。

/*** 扩展类加载器*/
public class ExtClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = ScriptEnvironment.class.getClassLoader();System.out.println(classLoader);}
}

打印结果如下:

在这里插入图片描述

通过扩展类加载器去加载用户jar包:
  • 放入/jre/lib/ext下进行扩展。不推荐,尽可能不要去更改JDK安装目录中的内容。
  • 使用参数进行扩展使用参数进行扩展。推荐,使用-Djava.ext.dirs=jar包目录进行扩展,这种方式会覆盖掉原始目录,可以追加上原始目录,并使用 ;(windows系统所用符号) :(macos/linux) 进行分隔

如下图中:

在这里插入图片描述

使用引号将整个地址包裹起来,这样路径中即便是有空格也不需要当做特殊字符额外处理。路径中要包含原来ext文件夹,同时在最后加上扩展的路径。

  1. 应用程序加载器

应用程序类加载器会加载classpath下的类文件,默认加载的是项目中的类以及通过maven引入的第三方jar包中的类。

如下案例中,打印出Student(自己写的)和FileUtils(引入的)的类加载器:

/*** 应用程序类加载器案例*/
public class AppClassLoaderDemo {public static void main(String[] args) throws IOException, InterruptedException {//当前项目中创建的Student类Student student = new Student();ClassLoader classLoader = Student.class.getClassLoader();System.out.println(classLoader);//maven依赖中包含的类ClassLoader classLoader1 = FileUtils.class.getClassLoader();System.out.println(classLoader1);Thread.sleep(1000);System.in.read();}
}

输出结果如下,这两个类均由应用程序类加载器加载。

在这里插入图片描述

Arthas中类加载器相关功能

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

在这里插入图片描述

查看应用程序类加载器所加载的jar包

在这里插入图片描述

文章说明

该文章是本人学习 黑马程序员 的学习笔记,文章中大部分内容来源于 黑马程序员 的视频黑马程序员JVM虚拟机入门到实战全套视频教程,java大厂面试必会的jvm一套搞定(丰富的实战案例及最热面试题),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对 黑马程序员 的优质课程表示感谢。

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

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

相关文章

[C++核心编程-01]----C++内存四区详细解析

目录 前言 正文 01-内存区域简介 02-全局区 03-栈区 04-堆区 05-new操作符 总结 前言 当程序运行时,操作系统会为程序分配一块内存空间,这块内存空间被划分为不同的区域,每个区域有其独特的作用…

赶紧收藏!2024 年最常见 100道 Java 基础面试题(四十二)

上一篇地址:赶紧收藏!2024 年最常见 100道 Java 基础面试题(四十一)-CSDN博客 八十三、OSI的七层模型都有哪些? OSI(Open Systems Interconnection)参考模型是一个七层的网络通信模型&#xf…

python自定义x坐标名称

在画完图后加上 x[0.1,0.5,1.0,2.0,4.0,6.0,8.0] plt.xticks(x) import matplotlib.pyplot as pltx [1, 2, 3, 4, 5] y [2, 4, 6, 8, 10]plt.plot(x, y) plt.xticks(x, [A, B, C, D, E]) # 设置x轴坐标位置和标签 plt.show()要自定义x坐标名称,你可以使用matplo…

Unity图形图表XChart插件使用

最近做了一款数字孪生项目,其中涉及到了图形图表的应用,网上找了一下,找到了XChart插件,使用起来蛮方便的,不过还有待继续研究,很多细节性的知识点需要进行学习探索。以下是项目中的应用。 官方应用: ![](https://img-blog.csdnimg.cn/direct/ab9de8e84e7b4be4a50ea…

双指针算法(判断子序列,最长连续不重复子序列)

一.判断子序列 编程题 题目描述: 给定一个长度为 n 的整数序列 a1,a2,…,an 以及一个长度为 m 的整数序列 b1,b2,…,bm。 请你判断 a 序列是否为 b 序列的子序列。 子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5} 是序列 {a1…

vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题

(1)学习线程,与学习其它容器一样,要多读 STL 库的源码。很多知识就显然而然的明白了。也不用死记硬背一些结论。上面上传了一份注释了一下的 源码。主要是补充泛型推导与函数调用链。基于注释后的源码探讨几个知识点。 STL 库的多…

哈希(构造哈希函数)

哈希 哈希也可以叫散列 画一个哈希表 哈希冲突越多&#xff0c;哈希表效率越低。 闭散列开放定址法: 1.线性探测&#xff0c;依次往后去找下一个空位置。 2.二次探测&#xff0c;按2次方往后找空位置。 #pragma once #include<vector> #include<iostream> #i…

Linux重定向及缓冲区理解

重定向&#xff1a; 在上一期虚拟文件系统中讲到了每个进程在打开后&#xff0c;都会默认打开3个文件&#xff0c;如下&#xff1a; stdin 标准输入&#xff08;键盘&#xff09; 文件描述符&#xff1a;0 stdout 标准输出&#xff08;显示器&#xff09;文件描述符&a…

每日OJ题_贪心算法四⑤_力扣354. 俄罗斯套娃信封问题

目录 力扣354. 俄罗斯套娃信封问题 解析代码1_动态规划&#xff08;超时&#xff09; 解析代码2_重写排序贪心二分 力扣354. 俄罗斯套娃信封问题 354. 俄罗斯套娃信封问题 难度 困难 给你一个二维整数数组 envelopes &#xff0c;其中 envelopes[i] [wi, hi] &#xff0…

25计算机考研院校数据分析 | 中南大学

中南大学&#xff08;Central South University&#xff09;&#xff0c;位于湖南省长沙市&#xff0c;是中华人民共和国教育部直属的全国重点大学 &#xff0c;中央直管副部级建制&#xff0c;位列国家“双一流”、“985工程”、“211工程”&#xff0c;入选国家“2011计划”牵…

陪玩系统APP小程序H5音视频社交系统陪玩系统源码,陪玩app源码,陪玩源码搭建陪玩社交系统开发(现成,可定制)线下陪玩系统项目开发搭建

线下陪玩系统项目的设计 在需求分析完成后&#xff0c;接下来进行系统设计。系统设计主要包括以下几个部分&#xff1a; 1. 数据库设计&#xff1a;根据需求分析的结果&#xff0c;设计数据库结构&#xff0c;包括用户信息表、服务信息表、订单信息表等。 2. 界面设计&#…

阮怀俊参与五龙乡黄沙村村企联办“强村公司”

为走好海岛县高质量发展共同富裕特色之路&#xff0c;探索村级集体经济发展新路径、扶持新模式、运行新机制&#xff0c;嵊泗县五龙乡黄沙村股份经济合作社与杭州山舍乡建乡村产业发展有限责任公司联办成“强村公司”。 创始人阮怀俊表示&#xff0c;双方就融合乡域发展和文旅产…

训练时候查看gpu溢出情况

训练时候查看gpu溢出情况 pytorchtensorflow 训练时候查看gpu溢出情况 #深度学习/gpu相关代码 pytorch 我可以帮您了解如何在 GPU 溢出的时候给您提示。 使用 try-except 语句来捕获 CUDA out of memory 的异常&#xff0c;并在发生异常时打印提示信息。例如&#xff0c;您可…

MFC桌面应用中窗口的客户区与非客户区的

在MFC&#xff08;Microsoft Foundation Class&#xff09;中&#xff0c;窗口被分为客户区和非客户区。理解这两个概念对于设计和开发Windows应用程序至关重要。 客户区&#xff08;Client Area&#xff09;&#xff1a; 客户区是窗口中用于显示应用程序内容的区域。它是窗口…

PXE高效批量装机

一、PXE的概述 PXE是由Inter 公司开发的网络引导技术&#xff0c;工作在Client / Server 模式。允许客户机通过网络从远程服务器下载引导镜像&#xff0c;并加载安装文件或者整个操作系统。 1.1PXE优点 规模化&#xff1a;同时装配多台服务器 自动化&#xff1a;安装系统&am…

Flutter “Hello World“ 开发教程

Flutter “Hello World” 开发教程 简介 Flutter 是 Google 开发的一个开源移动应用 SDK&#xff0c;用于帮助开发者快速高效地构建跨平台的移动应用。它使用 Dart 语言&#xff0c;并且支持热重载功能&#xff0c;可以即时查看代码更改的效果。本教程将带你创建一个简单的 F…

Vue3知识总结-3

标题# Vue3知识总结-3 模版引用 需要直接访问底层的dom元素&#xff0c;要使用ref这个attribute,挂载结束后引用都会暴露在this.$refs上面 <template> <div ref"container" class"container">{{content}}</div><input type"t…

力扣10.正则表达式匹配

前言&#xff1a; 由于今天面试前端&#xff0c;面试官问对正则表达式的匹配理解吗&#xff1f; 当时脑袋发热&#xff0c;我说就是对字符串的替换。。。。 太抽象了&#xff0c;于是我面试结束后马上打开力扣&#xff0c;解了正则表达式的匹配算法题(四种语言)&#xff1b; 下…

03c++重载运算符

1、深入理解new和delete原理 #include<iostream> using namespace std;/* new 和 delete 1、malloc和new的区别 new 内存开辟构造函数 2、free和 delete的区别 delete 内存回收析构函数 开辟失败malloc返nullptr ,new抛出bad_alloc异常new->operator new delete -&…

TCL/TK GUI in Python 浅试笔记

TK GUI 学习 Tk 使用单线程、事件驱动的编程模型. 所有 GUI 代码、事件循环和 应用程序在同一线程中运行。因此&#xff0c;强烈建议不要进行任何阻止事件处理程序的调用或计算。 耗时操作的处理&#xff1a; 如果需要从另一个线程与运行 Tkinter 的线程进行通信&#xff0c…