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

news2024/11/28 18:41:13

文章目录

    • 类加载器
      • 什么是类加载器
      • 类加载器的作用是什么
      • 应用场景
      • 类加载器的分类
        • 启动类加载器
          • 用户扩展基础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.coloradmin.cn/o/1668354.html

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

相关文章

【Gitlab远程访问本地仓库】Gitlab如何安装配置并结合内网穿透实现远程访问本地仓库进行管理

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具&#xf…

数据结构与算法学习笔记之线性表二---顺序表的静态存储表示和实现(C++)

目录 前言 1.什么是顺序表 2.顺序表的静态存储表示 1.初始化 2.长度 3.数据元素 4.长度 5.获取元素下标 6.前驱节点 7.后继节点 8.插入 9.删除 10.遍历 11.测试代码 前言 这篇文章讲的是顺序表的两种实现方式。 1.什么是顺序表 线性表的顺序表示指的是用一组地址…

用hMailServer+roundcubemail+宝塔安装配置一个自己的邮箱服务

用hMailServerroundcubemail安装配置一个自己的邮箱服务 1、准备工具与资料: 云服务器一台 基础配置就行 2核4G。域名一个 以下用lizipro.cn示例。hMailServer安装包roundcubemail安装包异常处理插件补丁: libmysql.zip 2、hMailServer服务安装&#…

通过内网穿透免费部署我们的springboot+vue项目 实现跟服务器一样的效果

前文讲到通过内网穿透能够实现远程访问个人电脑的静态资源。本文将讲解通过内网穿透实现远程访问本地的项目,实现跟部署到服务器一样的效果:前文链接:通过内网穿透实现远程访问个人电脑资源详细过程(免费)(…

MFC重要的初始化函数InitInstance

MFC应用程序最早处理的类的初始化函数通常是CWinApp类的构造函数。CWinApp类是MFC应用程序的主类,负责整个应用程序的初始化和管理。 在MFC应用程序中,通常会创建一个派生自CWinApp类的应用程序类,例如CMyApp。在应用程序启动时,…

MySQL——系统变量

使用 #最大连接用户数 select MAX_CONNECTIONS; #临时存放构成每次事务的SQL的缓冲区长度 select BINLOG_CACHE_SIZE; #SQL Server的版本信息 select VERSION; 查询结果

Linux实验 系统管理(三)

实验目的: 了解Linux系统下的进程;掌握一类守护进程——计划任务的管理;掌握进程管理的常用命令;掌握进程的前台与后台管理;了解Linux系统的运行级别;掌握系统服务管理的常用命令。 实验内容: …

可视化大屏:城市治理方向,三维地图那是相当震撼呀。

随着城市化进程的加快,城市治理变得越来越复杂,需要大量的数据和信息来支持决策和管理。在这个背景下,可视化大屏作为一种新兴的信息展示工具,正逐渐在城市治理中发挥着重要作用。 首先,可视化大屏能够将庞大的数据和信…

Web前端一套全部清晰 ⑧ day5 CSS.3 选择器、PxCook软件、盒子模型

谁不是一路荆棘而过呢 —— 24.5.12 CSS.3 选择器、PxCook软件、盒子模型 一、选择器 1.结构伪类选择器 1.作用: 根据元素的结构关系查找元素。 选择器 说明 E:first-child 查找第一个 E元素 E:last-child 查找最后一个E元素 E:nth-chil…

数据结构·一篇搞定栈!

好久不见,超级想念 废话不多说,直接看 引言 在数据结构的大家族中,栈(Stack)是一种非常重要的线性数据结构,它的特点是后进先出(LIFO,Last In First Out)。栈在程序设…

docker八大架构之单机架构

单机架构 什么是单机架构? 单机架构指的是应用服务和数据库服务公用同一台服务器。如下边两个图所示,当我们进行购物时,所有的物品信息和用户信息都是在同一个服务器下进行运行的,之所以称为单机架构就是因为它所有的操作是在同…

【AMBA Bus ACE 总线10 -- ACE Barrier transaction 详细介绍】

请阅读【AMBA Bus ACE 总线与Cache 专栏 】 欢迎学习:【嵌入式开发学习必备专栏】 文章目录 ACE AxBARAxBAR[1:0]的值及含义屏障的用途和重要性ACE AxBAR 用于表明是否是一个barrier 的transaction,对于它我们只需要有个简单的了解即可,现在已经不建议在transaction的层面上…

Unity VR在编辑器下开启Quest3透视(PassThrough)功能

现在有个需求是PC端串流在某些特定时候需要开启透视。我研究了两天发现一些坑,记录一下方便查阅,也给没踩坑的朋友一些思路方案。 先说结论,如果要打PC端或者在Unity编辑器中开启,那么OpenXR当前是不行的可能还需要一个长期的过程,必须需要切换到Oculus。当然Unity官方指…

异常处理/ROS2异常处理模块源码解读与浅析

文章目录 概述ros2/rcutils/src/error_handling模块自身异常处理错误状态结构与存储本模块初始化错误状态的设置错误状态的获取错误状态的清理不丢失旧错误状态把手段还原为目的其他 概述 本文从如下几个方面对 ROS2.0 中 rcutils 库 error_handling 错误处理模块的源码进行解…

整理好的中债国债3年期到期收益率数据集(2002-2023年)

01、数据简介 国债,又称国家公债,是由国家发行的债券,是中央ZF为筹集CZ资金而发行的一种ZF债券,是中央ZF向投资者出具的、承诺在一定时期支付利息和到期偿还本金的债权债务凭证。 中债,是指由中国中债登记结算有限责…

报表-接口类型的数据源

1、配置 在数据中进行如下配置 配置格式,换行的方式 #API $.data[0].children http://192.168.1.1:9200/apis/getInfo 行1:固定写法,标识这是一个接口类型的数据集 行2:JSONPath格式字符串,对接口的数据进行取值。…

轮转数组 与 消失的数字

轮转数组 思路一 创建一个新内存空间,将需轮转的数依次放入,之后在把其它数放入 代码: void rotate(int* nums, int numsSize, int k) {k k % numsSize;// 确定有效的旋转次数if(k 0)return;int* newnums (int*)malloc(sizeof(int) * nu…

Linux与Windows互传文件【笔记】

Linux与Windows互传文件【笔记】 前言前言推荐Linux与Windows互传文件首先确保Windows安装ssh如何传送文件问题 最后 前言 这是陈旧已久的草稿2023-05-10 00:01:24 这个是准备把计组课程华为智能计组的,传输文件。 最后发现,好像没有实现了。 现在202…

云器Lakehouse:Multi-Cluster弹性架构如何实现湖上高并发低延迟分析

导读 在当今快速发展的大数据时代,数据平台的性能和效率对于企业来说至关重要。云器Lakehouse的Multi-Cluster弹性架构为我们提供了一种全新的视角,以应对数据湖上高并发和低延迟分析的挑战。本文将深入探讨云器Lakehouse如何通过其独特的技术理念和架构…

MySql软件安装

1.打开mysql官网网址 MySQL :: Download MySQL Community Server 2.本次针对版本8的图形化界面安装,下载成功后接下来对MySQL进行安装 3.图形化下载后有一个MSI文件 4.我们安装典型即可,选择第一个 5.选择数据库信息存放的路径,我默认放在C盘…