JVM二:JVM类加载机制
目录
前言
1.什么是类加载?
2.类加载整体流程
3.一个类什么时候被加载?
4.双亲委派模型
4.1 JVM默认提供了三个类加载器
4.1.1 BootstrapClassLoader
4.1.2 ExtensionClassLoader
4.1.3 ApplicationClassLoader
4.2 破坏双亲委派模型
前言
在上一篇文章中,我们主要简述了JVM内存区域划分的相关知识,下面我们将讲述JVM类加载机制
1.什么是类加载?
类加载就是.class文件(.java通过javac进行编译成class文件),从文件(硬盘)被加载到内存中(元数据区)的过程。
2.类加载整体流程
- 1.加载:把.class文件找到,打开文件,读文件,把文件内容读到内存中;
- 2.验证:检查下.class文件格式是否规范;
- 3.准备:给类对象分配内存空间(先在元数据占个位置),也使静态成员被设置成0;
- 4.解析:初始化字符串常量,把符号引用转为直接引用。初始化字符串常量时,首先需要为字符的实际内容分配一块内存空间,并确保有一个引用指向这块内存空间的起始地址。在类加载之前,字符串常量存在于.class文件中,这个"引用"记录的是它在文件中的偏移量(占位符),而不是字符串常量的真正地址。当类加载完成后,字符串常量才会被放入内存中,此时引用会被赋值为实际的内存地址。
- 举例:假设你得到了一张古老的藏宝图,这张藏宝图标记了一处隐藏的宝藏位置。这个过程与字符串常量的处理有类似之处:
-
1. 藏宝图的研究(类加载前):在开始挖掘宝藏之前,藏宝图就像是一个.class文件里的字符串常量。你知道这张图代表了什么,但还没有实际的行动。图中标记的位置不是真实的地址,而是告诉你宝藏可能在哪里的一种“偏移量”或线索;
-
2. 准备挖掘(类加载):决定根据藏宝图去探险,就好比是类加载的过程。你开始准备必要的工具,如铲子和地图,这相当于JVM为字符串常量分配内存空间;
-
3. 定位宝藏(引用转换):出发后,你按照藏宝图上的线索前进,这如同符号引用被转换为直接引用。你通过解读地图上的线索(可能是一棵树、一块石头或一个特定形状的地标),逐步接近宝藏的实际位置。
-
4. 挖掘宝藏(访问地址):当你到达指定地点并开始挖掘时,这就像是JVM访问字符串常量在内存中的实际位置。你挖出宝藏的那一刻,就类似于程序最终使用到这个字符串常量的内容。
通过这个例子,我们可以看到,藏宝图的使用过程(从解读到实际挖掘出宝藏)与JVM如何处理字符串常量(从类加载到实际使用字符串内容)有着相似的步骤。都是先有一个初步的指引(无论是藏宝图还是符号引用),然后通过一系列的动作(解读和应用),最终达到目的(找到宝藏或获取字符串内容)。
- 5.初始化:调用构造方法,进行成员初始化,执行代码块,静态代码块,加载父类等。
3.一个类什么时候被加载?
- 首先我们要知道,不是Java程序一运行,就把所有的类都加载,而是真正用到才加载(懒汉模式),一旦加载过后,后续无需再重复加载;
- 加载的内容有:
- 1.构造类的实例;
- 2.调用这个类的静态方法/使用静态属性;
- 3.加载子类,就会先加载其父类
4.双亲委派模型
在上面的类加载的整体流程中,我们说到了加载,
加载:把.class文件找到,打开文件,读文件,把文件内容读到内存中
- 双亲委派模型描述了类加载器在查找和加载.class文件时的基本过程。
-
4.1 JVM默认提供了三个类加载器
-
4.1.1 BootstrapClassLoader
- 负责加载标准库的类
- (Java规范,要求提供哪些类)无论是哪种JVM的实现,都会提供这些一样的类
- 负责加载标准库的类
-
4.1.2 ExtensionClassLoader
- 负责加载JVM扩展库中的类
- (规范之外,由实现JVM的厂商/组织,提供的额外的功能)
- 负责加载JVM扩展库中的类
-
4.1.3 ApplicationClassLoader
- 负责加载用户提供的第三方库/用户项目代码中的类
- 上述的三个类存在"父子关系",相当于每个class loader有一个parent属性,指向自己的父 类加载器
- 4.1.4 上述的类加载器如何配合工作?
- 1.首先,类加载过程是从ApplicationClassLoader开始的。然而,ApplicationClassLoader不会直接进行加载,而是将加载任务委托给自己的父 类加载器。接下来,ExtensionClassLoader接收到委托后,同样不会立即加载,而是再次将自己作为父类加载器,并将加载任务委托给它的父 类加载器BootstrapClassLoader。BootstrapClassLoader在收到委托时,发现自己没有父类加载器(即父类为null),于是它自己执行实际的加载操作。
- 2.BootstrapClassLoader会搜索自己负责的标准库目录,寻找相关的类。如果找到了目标类,则进行加载;如果没有找到,它会将加载任务委托给子类加载器。ExtensionClassLoader会真正地搜索扩展库相关的目录,同样地,如果找到了目标类,则进行加载;如果没有找到,它也会将加载任务委托给子类加载器。ApplicationClassLoader则会搜索用户相关的目录,如果找到了目标类,则进行加载;如果没有找到,由于此时已经没有其他子类加载器了,所以只能抛出一个类找不到的异常。
- 3.为什么要有上述顺序?
- 上述这套顺序实际上是由JVM实现代码的逻辑所决定的,这种逻辑类似于递归的方式;
- 主要目的是确保Bootstrap能够优先加载,而Application能够稍后加载,以避免用户创建一些奇怪的类,从而引发不必要的bug;
- 在一方面,类加载器可以由用户自定义。除了JVM自带的Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader之外,用户可以创建自己的类加载器,并将其加入到类加载流程中。这样,用户可以根据自己的需求决定加载顺序,并且可以与现有的加载器配合使用。
-
4.2 破坏双亲委派模型
1.自己编写的类加载器可以根据需求选择是否遵守双亲委派模型。
2.举例来说,Tomcat是一个Web服务器,它需要加载Web应用程序中的类。在这种情况下,Tomcat可能会使用单独的类加载器来加载Webapp,而不是遵循双亲委派模型。
3.这样做的好处是可以避免不同Web应用程序之间的类冲突,并且可以更好地控制每个Web应用程序的类加载过程。然而,如果一个自定义的类加载器不遵循双亲委派模型,那么它必须自行处理类的查找和加载,这可能会导致一些额外的复杂性和潜在的问题。因此,是否遵守双亲委派模型主要取决于具体的需求和设计决策。
以上就是JVM类加载机制的简单介绍。
相关文章:

JVM二:JVM类加载机制
目录 前言 1.什么是类加载? 2.类加载整体流程 3.一个类什么时候被加载? 4.双亲委派模型 4.1 JVM默认提供了三个类加载器 4.1.1 BootstrapClassLoader 4.1.2 ExtensionClassLoader 4.1.3 ApplicationClassLoader 4.2 破坏双亲委派模型 前言 在上一篇文章中…...

对于springboot无法连接redis解决方案
对于springboot无法连接redis解决方案 一、测试是否能在本地应用上访问到你的redis(如果是部署在linux上的话)1. 开启telnet功能2. 开始测试端口是否能访问到(适用于所有,包括MQ)3. 开放6379端口4. 看spring的配置文件…...

关于android中的各种尺寸与计算
--张学友《心如刀割》很好听 先说几个术语: Screen size(屏幕尺寸): 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 摩托罗拉milestone手机是3.7英寸 Aspect Ratio(宽高比率)&am…...

MySQL避免索引失效的方法详细介绍
避免索引失效 在MySQL中,索引是帮助MySQL高效获取数据的数据结构。它就像一本书的目录,通过索引可以快速定位到数据的具体位置,从而减少对数据库的扫描量,提高查询速度。索引可以存储在表中的一个或多个列上,创建索引…...

【Java】深入了解 Java 的 charAt() 方法
我最爱的那首歌最爱的angel 我到什么时候才能遇见我的angel 我最爱的那首歌最爱的angel 我不是王子也会拥有我的angel 🎵 张杰《云中的angel》 在 Java 编程中,字符串(String)是我们经常处理的数据类型之一。…...

Linux 下 ETCD 安装、配置与命令使用总结
大家好,我是程序员小羊! 前言: Linux 下 ETCD 安装、配置与命令使用总结 ETCD 是一个分布式键值存储系统,广泛用于服务发现、分布式锁、配置管理等场景,特别是在 Kubernetes 集群中发挥着至关重要的作用。ETCD 的高…...

C++笔试练习笔记【7】:力扣 91. 解码方法 动态规划练习
文章目录 题目题目分析思路解法正常解法优化解法 题目 题目链接:力扣 91. 解码方法 备用链接:https://leetcode.cn/problems/decode-ways/description/ 题目分析 1.首先我们知道题目给定A~Z编码为1 ~26 ,而数字十一字符串的形式给出所以…...

【antd】antd3的表单校验不提示报错信息
描述 不是网上所谓的自定义校验方法的问题。 今天在写一个antd3的业务的时候,封装一个组件,把校验和请求事件放在一个方法里面,用回调或者promise进行异步处理。 发现原因是在校验错误的判断,进行callback之后,页面…...

Game AI ——游戏人工智能(逻辑及剧情生成)
一、Game AI 的介绍 "Game AI"(游戏人工智能)通常指的是在电子游戏中使用的各种人工智能技术和算法,用于控制游戏中的非玩家角色(NPC)、敌人、队友等,以及为玩家提供有挑战性的对手或有趣的互动…...

算法基础知识——核函数
简介:个人学习分享,如有错误,欢迎批评指正 核函数(Kernel Function)是机器学习中一种重要的工具,特别是在支持向量机(SVM)、核岭回归、核主成分分析(KPCA)等核…...

安卓xml乱码/加密转换:abx2xml和xml2abx使用及源码介绍
背景: 上一篇文章 android系统中data下的xml乱码无法查看问题剖析及解决方法 发布后,想要寻找一个可以直接把二进制xml和普通xml进行相互转换的,当时还写了相关的方案,但是当时没有找到现成的开源工具,后来经过相关粉…...

slice 截取
JavaScript中的一个数组方法。然而,在Vue 3的应用开发中,slice 方法经常被用于处理数组数据,特别是在需要实现分页、数据截取或数据展示等场景时。 slice 方法的基本用法 slice() 方法返回一个新的数组对象,这一对象是一个由 be…...

XReparentWindow踩坑分析
X11是Linux发行系统中广泛采用的显示协议,各个系统基本上都支持XLib库,作为底层接口,XReparentWindow接口的功能就是重新设置父窗口,注意这个可以跨进程设置父窗口,例如将已经运行的进程的父窗口设置自己的程序Wid&…...

OpenAI动荡,将走向何方、GPT5或许将近、毒舌AI轻松破防网友、最新版 GPT-4o AI 模型得满分 | AGI视界周刊第 4 期
AI 视界周刊由战场小包维护,每周一更新,包含热点聚焦、应用破局、学术前沿、社区热议、智见交锋、跨界 AI、企业动态和争议 AI 八大板块,后续板块划分和内容撰写在周刊迭代过程中持续优化,欢迎大家提出建议。 欢迎大家来到《AI 视…...

RCE---无字母数字webshell
<?php if(isset($_GET[code])){$code $_GET[code];if(strlen($code)>35){die("Long.");}if(preg_match("/[A-Za-z0-9_$]/",$code)){die("NO.");}eval($code); }else{highlight_file(__FILE__); } 分析代码:传参不大于35&…...

有意思的漏洞复现与分析一
目录 一、Linux命令长度限制突破方法 1.在二进制漏洞利用中,某师傅遇到可控数据只有8字节的情况,去掉字符 串尾的\0,限制在7个字符。 一、Linux命令长度限制突破方法 1.在二进制漏洞利用中,某师傅遇到可控数据只有8字节的情况&a…...

力扣题解(按身高排序)
2418. 按身高排序 给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i,names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 思路&…...

Redis的六种淘汰策略详解
Redis作为一种高性能的键值对存储系统,其数据全部存储在内存中,因此内存管理对Redis的性能至关重要。当Redis的内存使用达到上限时,就需要通过淘汰策略来释放内存空间,以便存储新的数据。Redis提供了六种不同的淘汰策略࿰…...

vue3中 ref 和 reactive 的区别
相同:均是声明响应式对象。且声明的响应式对象是深层的 1. 数据类型不同:ref用于包装JavaScript基本类型的数据(如字符串、数字、布尔值等),而reactive可以用于包装JavaScript对象和数组等复杂类型的数据。 2.访问方式…...

《单例模式的深度解读:实现方式、破坏情况与利弊权衡》
单例模式 一、单例模式的定义 单例模式(Singleton Pattern)是一种常见的软件设计模式,确保一个类只有一个实例存在,并提供一个全局访问点来获取该实例。 二、单例模式的实现方式 1.懒汉式单例 public class LazySingle…...

010607电压源和电流源受控源
电源的理论部分 1.6电压源和电流源1.理想电压源: 1.6电压源和电流源 1.理想电压源: 其两端电压总能保持定值或一定的时间函数,其值与流过它的电流i无关的元件叫理想电压源。 电路符号:中间与导线直通的圆圈 电压源:…...

快乐数求解
编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1,…...

运维高级内容--为端口做标记、制定调度规则
rs: yum install mod_ssl -y #安装mod_ssl模块 让rs支持https systemctl restart http lvs: cd /boot/ ls less config-5.14.0-427.13.1.el9_4.x86_64 ipvsadm -A -t 192.168.0.200:80 -s rr ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1 #轮询调度一次…...

后端Web之HTTP协议基础介绍
目录 1.HTTP概念 2.HTTP请求协议 3.HTTP响应协议 4.HTTP协议解析 1.HTTP概念 HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网数据通信的基础,允许将超…...

深入解析Nginx限流策略:如何高效控制访问频率
摘要:本文将详细介绍Nginx限流模块的使用方法,包括基于IP地址的限流、基于并发连接的限流以及如何应对突发流量。通过实际案例,帮助读者掌握Nginx限流策略,确保服务器在高并发场景下的稳定运行。 一、引言 在高并发场景下&#x…...

锂电池剩余寿命预测 | Matlab基于Transformer-GRU的锂电池剩余寿命预测
目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于Transformer-GRU的锂电池剩余寿命预测,Transformer结合门控循环单元。 Matlab基于Transformer-GRU的锂电池剩余寿命预测(单变量) 运行环境Matlab2023b及以上。 首先从…...

深入理解Spring的IOC容器与依赖注入
深入理解Spring的IOC容器与依赖注入 引言 Spring框架的核心功能之一就是它的IOC容器,它为开发人员提供了强大的依赖管理和控制反转的能力。本文将详细介绍Spring的IOC容器以及依赖注入的基本概念和实现方式,并通过示例展示如何在实际项目中应用这些技术…...

Qt读写sysfs
本文介绍Qt读写sysfs。 在嵌入式Linux系统上开发Qt应用程序,经常会涉及到外设的控制,比如GPIO,PWM的控制,Linux环境下可以像操作文件一样操作它们,这通常会涉及到sysfs的读写。本文以读写GPIO为例,简要介绍…...

实景三维:解锁地理信息新维度,引领未来城市智慧之钥
在这个信息爆炸与科技日新月异的时代,地理信息与遥感技术正以前所未有的速度改变我们认知世界的方式。在推动“实景三维平台”这一前沿科技的构建上,它不仅是地理信息的立体呈现,更是智慧城市的基石,打开了通往未来城市规划、管理…...

汽车免拆诊断案例 | 2010款劳斯莱斯古斯特车中央信息显示屏提示传动系统故障
故障现象 一辆2010款劳斯莱斯古斯特车,搭载N74发动机,累计行驶里程约为11万km。车主反映,起动发动机后组合仪表和中央信息显示屏均提示传动系统故障。用故障检测仪检测,发现发动机控制模块2(DME2)中存储…...