全网最强最详细的JVM类加载机制详解!看完不要再说不会了!

JVM (三) - 类加载机制 通常情况下,我们都是直接使用系统类加载器。但是,有的时候,我们也需要自定义类加载器。比如应用是通过网络来传输 Java 类的字节码,为保证安全性,这些字节码经过了加密处理,这时系统类加载器就无法对其进行加载,这样则需要自定义类加载器来实现。自定义类加载器一般都是继承自 ClassLoader 类,从上面对 loadClass 方法来分析来看,我们只需要重写 findClass 方法即可。try { 阅读详情

类加载机制

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

PS:记得点赞收藏加关注哦 ,需要下载PDF版本和更多知识点、面试题的朋友可以点一点下方链接免费领取

链接:点这里!!! 799215493 暗号:优快云

在这里插入图片描述

类加载的时机

  • 遇到new(比如new Student())、getstatic和putstatic(读取或设置一个类的静态字段,如下代码,读取被final修饰并已在编译器把结果放入常量池的静态字段除外)、invokestatic(调用类的静态方法)这四条指令时,如果对应的类没有初始化,则要对对应的类先进行初始化。
public class Student{
	private static int age;
	public static void method(){
	}
}
Student.age
Student.method();
  • 使用java.lang.reflect包方法时对类进行反射调用的时候。
  • 初始化一个类的时候发现其父类还没初始化,要先初始化其父类。
  • 当虚拟机开始启动时,用户需要指定一个主类(main),虚拟机会限制性这个主类的初始化。

类加载的过程

类加载过程是如下图所示的一个流水线过程,其中连接过程可细化为验证、准备和解析三个小步骤。

在这里插入图片描述

加载

class文件–>class对象

“加载”过程主要是靠类加载器实现的,包括用户自定义类加载器。

在这里插入图片描述

加载的过程

在加载过程中,JVM主要做以下3件事:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流(class文件)。在程序运行过程中,当要访问一个类时,若发现这个类尚未被加载,并满足类初始化的条件时,就根据要被初始化的这个类的全限定名找到该类的二进制字节流,开始加载过程
  2. 将这个字节流的静态存储结构转化为方法区的运行时数据结构(即Class对象)
  3. 在内存中创建一个该类的java.lang.Class对象,作为方法区该类的各种数据的访问入口

程序在运行中所有对该类的访问都通过这个类对象,也就是这个Class对象是提供给外界访问该类的接口。

加载源

JVM规范对于加载过程给予了较大的宽松度,一般二进制字节流都从已经编译好的本地class文件中读取,此外还可以从这些地方读取:zip包(jar、war、ear等),由jsp文件中生成对应的Class类,数据库,网络,运行时计算生成(动态代理技术)。

加载过程的注意点

  • 类和数组加载的区别:非数组类是由类加载器来完成;数组类本身不通过类加载器创建,它是由java虚拟机直接创建,但数组类与类加载器有很密切的关系,因为数组类的元素类型最终要靠类加载器创建。
  • HotSpot将Class对象存放在方法区

验证

各种检查

验证阶段比较耗时,它非常重要但不一定必要,可用-Xverify:none参数关闭,以缩短类加载时间。

验证的目的

保证二进制字节流的信息符合虚拟机规范,并没有安全问题。

验证的必要性

Java语言的安全性是通过编译器来保证的,但编译器和虚拟机是两个独立的东西,虚拟机只认二进制字节流,它不会管所获得的二进制字节流是哪来的。当然,如果是编译器给它的那么就相对安全,但如果是从其它途径获得的,那么无法确保该二进制字节流是安全的。

验证的过程

在这里插入图片描述
其中文件格式验证阶段是基于二进制字节流进行的,只有通过本阶段验证,才被允许存放到方法区。后面的三个验证阶段都是基于方法区的存储结构进行,不会再直接操作字节流。

准备

为static分配内存并初始化0值。JDK1.7之前在方法区,1.7之后在堆。

仅仅为类变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值即零值,这里不包含用final修饰的static,因为final在编译的时候就会分配好,同时这里也不会为实例变量分配初始化。类变量(静态变量)会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。

准备阶段主要完成两件事情:

  • 为已在方法区中的类的静态成员变量分配内存;
  • 为静态成员变量设置初始值,具体初始值为下图所示。

在这里插入图片描述
注意:

public static int x = 1000;

实际上变量x在准备阶段过后的初始值为0,而不是1000。将x赋值为1000是在初始化阶段完成。

解析

将符号引用替换为直接引用

解析是虚拟机将常量池的符号引用替换为直接引用的过程。

初始化

调用方法

初始化过程就是调用类初始化方法的过程,完成对static修饰的类变量的手动赋值还有主动调用静态代码块。

注意点:此步骤中虚拟机会保证在多线程环境中一个类的方法被正确地加锁(静态内部类)

类加载器介绍

在这里插入图片描述

启动类加载器:

由C++实现,不是ClassLoader子类。负责加载JAVA_HOME\lib目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt,jar)的类。

扩展类加载器:

负责加载JAVA_HOME\lib\ext目录中的,或通过java.ext.dirs系统变量指定路径中的类库。

应用程序类加载器:

负责加载用户路径(classpath)上的类库。

自定义类加载器:

上述的加载器只能加载指定目录下的jar和class,如果想加载其他位置的jar或类时,则需要实现自定义类加载器来加载。

比如要加载网络上的一个class文件,通过动态加载到内存之后,要调用这个类中的方法实现特定业务逻辑,此时默认的ClassLoader就不能满足我们的需求,需要定义自己的ClassLoader。

双亲委派模型

JVM的类加载是通过多层次的类加载器来完成的,类的层次关系和加载顺序可以由下图来描述:

在这里插入图片描述
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader组层检查,只要某个classloader已加载就视为已加载此类,保证此类只加载一次。而加载的顺序是自顶向下,也就是由上层来组层尝试加载此类。这种类加载的层次关系就是双亲委派模型。

需注意的点:

  • 当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器;
  • 只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。

为什么使用双亲委派这种模型

因为这样可以避免类的重复加载,当父classloader经加载了该类的时候,就没必要子classloader再加载一次。

考虑到安全因素,我们试想一下,如果不适用这种委托模型,那我们就可以随时使用自定义的String来动态替代java核心api重定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况。因为String已经在启动时就被Bootstrap ClassLoader加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非改编JDK中ClassLoader搜索类的默认算法。

判定两个Class对象是否相同的依据

  • class字节码是否相同
  • ClassLoader是否相同

JVM在判定两个class是否相同,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。类的全限定名完全相同,但是加载它的类加载器不同,那么在方法区中会产生不同的Class对象。

只有两者同时满⾜的情况下,JVM才认为这两个class是相同的。就算两个class是同⼀份class字节码,如果被两个不同的ClassLoader实例所加载,JVM也会认为它们是两个不同class。

破坏双亲委派模型 为什么需要破坏双亲委派

因为在某些情况下父类加载器需要加载的class文件由于受到加载范围的限制,父类加载器无法加载到需要的文件,这个时候就需要委托子类加载器进行加载。
双亲委派模型是在JDK1.2以后才使用的,但是有一些核心的API类在JDK1.2之前就已经写好了。

简单理解双亲委派模型是子类加载器去委托父类加载器完成类加载的工作,而破坏双亲委派模型是父类加载器去委托子类加载器完成类加载的工作。

以Driver接口为例,由于Driver接口定义在jdk当中,而其实现由各个数据库的服务商来提供,比如mysql就写了MySQL Connector,这些实现类都是以jar包的形式放到classpath目录下。

那么问题就来了,DriverManager(也由jdk提供,JDK1.2之前就写好了)要加载各个实现了Driver接口的实现类(在classpath下),然后进行管理,但是DriverManager由启动类加载器加载,只能加载JAVA_HOME\lib下的文件,而其实现是由服务商提供的,有系统类加载器加载,这个时候就需要启动类加载器来委托子类加载器来加载Driver实现,从而破坏了双亲委派。如下图所示。

在这里插入图片描述
在这里插入图片描述

总结

在这里也为大家整理了各个知识点模块整理文档(微服务、数据库、mysql、jvm、Redis等都有)和更多大厂面试真题,有需要的朋友可以点一点下方链接免费领取

链接:点这里!!! 799215493 暗号:优快云

在这里插入图片描述
在这里插入图片描述

深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器) 一、什么是类加载机制?虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。二、类加载的时机类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准(Preparation)、解析(Resolution)、初始化(Initial 阅读详情

相关推荐

(2024,DDPM,DDIM,流匹配,SDE,ODE)扩散:基础教程

本文的目标是尽可能简单地教授扩散。第一节介绍扩散的基本原理。第二节和第三节展示如何构建随机和确定性扩散采样器。第四部分介绍了密切相关的流匹配,可看作是扩散的推广。​第五节,强调实践中最重要的一些设计选择,包括采样器、噪声时间表和参数化方法。

qq_44681809的博客 1万+

JVM学习——类加载详解

类加载的时机 遇到new(比如new Student())、getstatic和putstatic(读取或设置一个类的静态字段,如下代码,读取被final修饰并已在编译器把结果放入常量池的静态字段除外)、invokestatic(调用类的静态方法)这四条指令时,如果对应的类没有初始化,则要对对应的类先进行初始化。 public class Student{ private static int age; public static void method(){ } } Student.age St

code_way的博客 1132

【验证技能树】UVM 源码解读01 -- UVM本质上就是软件工程方法论在芯片验证领域的应用

文章摘要: UVM(通用验证方法学)是基于SystemVerilog的芯片验证框架,采用组件化、面向对象和事务级抽象设计。其核心在于职责分离与数据流,通过Driver、Monitor、Sequencer等模块协作实现高效验证。UVM强调复用性、可扩展性和可维护性,类似软件工程的模块化与低耦合原则。理解其体系结构比记忆API更重要,有助于灵活组合组件并提升验证效率。UVM不仅是工具,更融合了软件工程思维,推动验证工作向自动化、系统化发展。掌握UVM底层逻辑能优化验证环境设计,适用于从IP到SoC的多层级验证场

qq_45869788的博客 1039

autowire加载指定实现类_【Spring】一个接口有多个实现类,如何指定一个实现类?@Resource、@Autowired、@Qualifier...

https://blog.youkuaiyun.com/qq_18298439/article/details/89175439如果一个接口有2个不同的实现, 那么怎么来Autowire一个指定的实现?举个例子:1、接口:ILayerpublic Interface ILayer{......}2、实现类:ImageLayerImpl ,实现了ILayer接口。@Service("imageLayerImpl...

weixin_39546501的博客 2496

WorkBuddy入门到 多Agent团队协作完全指南(附实操代码与配图)

WorkBuddy的Agent Teams功能支持多智能体协作,通过创建AI团队提升复杂任务处理效率。该功能支持自然语言创建团队、任务分配与依赖管理、成员间消息通信(包括直接消息和广播),并提供任务审批机制。典型应用场景包括软件开发、内容创作等协作任务。环境要求WorkBuddy 2026年3月及以上版本,支持Windows和macOS系统。用户可快速创建包含不同角色的AI团队,通过共享任务列表和信箱系统实现协作。高级功能包括委派模式、任务依赖管理和成员自主认领等,适合各类协作场景。

三棱球的专栏 6442

ARM架构下Horizon Client安装全攻略:从依赖检查到环境变量配置

本文详细介绍了在ARM架构设备上安装VMware Horizon Client的全过程,包括依赖检查、软件包获取、系统部署和环境变量配置。特别针对华为鲲鹏等ARM平台,提供了从基础准备到性能优化的完整指南,帮助用户高效完成虚拟桌面客户端的部署与调优。

github5actions的博客 551

Cortex-M3-指针和野指针

Cortex-M3-指针和野指针 什么是指针?指针在内存中实际上是一个无符号整数(unsigned int),但是它的值被赋予特殊的解释:表示变量或函数的地址。所以才被形象地称为“指针”,就好像指向谁家似的。在使用指针前,都必须先让它指向有意义的,并且允许由程序使用的实体——数据和代码。而所谓“野指针”,就是指某个指针变量的值因故超出合法的范围,使其“枪口”乱指。程序逻辑错误、数组越界、堆栈溢出、指针未经初始化、对缓存与缓冲的处理不当、多任务环境中的紊乱条件,甚至是恶意地破坏等,都可以制造出野指针。如

We are all in the gutter, but some of us are looking at the stars. 455

Qt Installer Framework 简单使用

qt installer framework 简单使用

qq_42815643的博客 2575

SpringIOC的注解应用

SpringIOC的注解应用1、使用注解的方式注册bean到IOC容器中2、定义扫描包时要包含的类和不要包含的类3、使用@AutoWired进行自动注入4、@AutoWired可以进行定义在方法上5、自动装配的注解@AutoWired,@Resource6、泛型依赖注入 ​ 在之前的项目中,我们都是通过xml文件进行bean或者某些属性的赋值,其实还有另外一种注解的方式,在企业开发中使用的很多,在bean上添加注解,可以快速的将bean注册到ioc容器。 1、使用注解的方式注册bean到IOC容器中 ap

EquinoxPrime的博客 458

YOLOv13有效涨点改进专栏目录 | 本专栏持续更新500+篇内容 | 包含各种卷积、主干网络、各种注意力机制、检测头、损失函数、小目标检测改进、二次创新模块、独家创新等几百种创新点改进

《YOLOv13改进专栏重磅更新》推出500+创新改进方案,涵盖卷积、主干网络、注意力机制、检测头等核心模块优化。专栏提供完整项目代码及答疑服务,包含YOLOv13网络结构解析、环境配置、模型训练全流程指导。内容分为八大模块:卷积优化、注意力机制、细节涨点、主干网络改进、特征融合、检测头优化、小目标检测及Mamba联合改进等,支持多种创新点组合应用,助力科研论文发表。现开放限时订阅,提供试读章节和详细技术解析。

Ai缝合怪、助力小伙伴高效发论文 3378

【ComfyUI专栏】ComfyUI 数字人方案-ComfyUI-EchoMimic

EchoMimic是一个基于图片和语音的数字人生成方案,通过ComfyUI节点实现。该方案安装简单,需下载特定模型文件(Unet、AudioProcessor和VAE)并保存本地。相比其他数字人生成方案,其节点操作更简便,支持多种Pose姿态选择,并能结合视频内容进行姿态同步,通过音频同步口型实现动态内容创建。生成的数字人效果直观,适用于快速创建个性化数字形象。

技术与管理的平衡木- 464

autowire加载指定实现类_Spring用@Autowire向一个类注入一个接口的两个实现类

@Servicepublic class AaaService implements IChangePassword {@Overridepublic void changePassword(String username, String password) {}}@Servicepublic class BbbService implements IChangePassword {@Overri...

weixin_32789583的博客 656

深度强化学习在足式机器人中的应用 (一):基础原理与仿真环境

我们将首先深入探讨其背后的核心挑战与技术栈,然后详细推导机器人学和强化学习的基本数学原理,特别是剖析在机器人控制领域表现卓越的PPO算法。下面的独立Python脚本展示了Isaac Gym的基本API用法,加载一个Go1机器人(假设URDF已准备好),并让它执行一个简单的预设动作(正弦波运动),以此来熟悉仿真流程。:代码的核心是直接操作GPU上的PyTorch张量,避免了CPU和GPU之间的数据拷贝,这是实现高性能的关键。:所有计算(如伪策略中的正弦波计算)都应该是向量化的,一次性为所有。

VectorShift的博客 228

JVM类加载过程

1. JVM类加载过程 1.概述 从类的生命周期而言,一个类包括如下阶段: 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序进行,而解析阶段则不一定,它在某些情况下可能在初始化阶段后在开始,因为java支持运行时绑定。 2. 类加载时机 加载(loading)阶段,java虚拟机规范中没有...

zhaocuit的博客 10万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

JVM 类加载机制详解

通过前面的分析,我们可以看出,除了和本地实现密切相关的启动类加载器之外,包括标准扩展类加载器和系统类加载器在内的所有其他类加载器我们都可以当做自定义类加载器来对待,唯一区别是是否被虚拟机默认使用。首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回;否则转入步骤2;委派类加载请求给父类加载器(更准确的说应该是双亲类加载器,真实虚拟机中各种类加载器最终会呈现树状结构),如果父类加载器能够完成,则返回父类加载器加载的Class实例;否则转入步骤3;

十年以上架构设计经验,专注于软件架构和人工智能领域,对机器视觉、NLP、音视频等领域都有涉猎 4780

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【JVM 基础】 Java 类加载机制

通常情况下,我们都是直接使用系统类加载器。但是,有的时候,我们也需要自定义类加载器。比如应用是通过网络来传输 Java 类的字节码,为保证安全性,这些字节码经过了加密处理,这时系统类加载器就无法对其进行加载,这样则需要自定义类加载器来实现。自定义类加载器一般都是继承自 ClassLoader 类,从上面对 loadClass 方法来分析来看,我们只需要重写 findClass 方法即可。try {

沁禹的博客 2129

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

JVM类加载机制

这些内存都将在方法区中分配。

xxxmine的博客 1021

全网最强 JVM 来袭!(至尊典藏版)

JVM 系列是我一直都不太想写的文章,主要是涉及的技术点太多了,而且很多小伙伴都用不上,写这篇文章大概花了近两个月的学习周期,其实作为 Java 必备技能之一,JVM还是非常重要的,所以感觉有必要对之前的 JVM 系列重新整理,单独出一篇文章。...

人生若只初相见@的博客 2万+

Android面试必备的JVM虚拟机制详解,看完之后简历上多一个技能!

网上高级工程师面试相关文章鱼龙混杂,要么一堆内容,要么内容质量太浅, 鉴于此我整理了上述安卓开发高级工程师面试题以及答案。希望帮助大家顺利进阶为高级工程师。目前我就职于某大厂安卓高级工程师职位,在当下大环境下也想为安卓工程师出一份力,通过我的技术经验整理了面试经常问的题,答案部分是一篇文章或者几篇文章,都是我认真看过并且觉得不错才整理出来。大家知道高级工程师不会像刚入门那样被问的问题一句话两句话就能表述清楚,所以我通过过滤好文章来帮助大家理解。现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕。

1005

JVM-类加载机制

Java虚拟机会把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称为虚拟机的类加载机制。与那些在编译时需要进行链接的语言不通,在Java语言里面,类型的加载、连接和初始化都是在程序运行期间完成的,这种策略会让Java语言进行提前编译时面临额外的困难,也会让类加载时稍微增加一些性能开销,但是却为Java应用提高了极高的扩展性和灵活性,Java天生可以动态扩展的语言特性就是依赖运行期间动态加载和动态连接这个特性实现的。

qq_63003916的博客 1573

JVM 基础 - Java 类加载机制

通常情况下,我们都是直接使用系统类加载器。但是,有的时候,我们也需要自定义类加载器。比如应用是通过网络来传输 Java 类的字节码,为保证安全性,这些字节码经过了加密处理,这时系统类加载器就无法对其进行加载,这样则需要自定义类加载器来实现。自定义类加载器一般都是继承自 ClassLoader 类,从上面对 loadClass 方法来分析来看,我们只需要重写 findClass 方法即可。try {

珍惜当下 949

jvm类加载机制概述

获取类的二进制字节流的阶段是我们java程序员最关注的阶段,也是操作性最强的一个阶段,因为这个阶段我们可以对我们的类加载器进行操作 ,比如我们想自定义类加载器进行操作完成加载,又或者我们想通过java agent来完成我们的字节码增强操作。验证(Verification):验证主要是为了保证被加载类的正确性,即装载的Class文件中的字节流保护的信息是否符合当前虚拟机的要求,并且还要求我们的信息不会危害虚拟机自身的安全,导致虚拟机的崩溃。类加载器除了用于加载类外,还可以用于确定类在java虚拟机的唯一性。

weixin_57763462的博客 1387

JVM类加载

负责读取java字节代码,并转换成java.lang.Class类的一个实例的代码模块类加载器除了用于加载类外,还可用于确定类在java虚拟机中的唯一性一个类在同一个类加载器中具有唯一性,而不同类加载器中允许同名类存在的,这里的同名是指全限定名相同,但是在整个JVM里,从然全限定名相同,若类加载器不同,则仍然不算做是同一个类,无法通过instanceOf,equals等方式的校验。

weixin_43860222的博客 942

JVM-虚拟机类加载机制

以一组符号来描述所引用的目标;符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用和虚拟机无关;在编译的时候每个java类都会被编译成一个class文件,但。

qq_74763440的博客 918

Jvm类加载机制详解--类加载的几个阶段

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机类加载机制。在Java语言中,类的加载、连接和初始化过程都是在程序运行期间完成的,这是java作为动态语言的基础。另外值得注意的是上面提到的Class文件,并不一定值得是磁盘上的.class文件,而只需要是任何符合字节码规范的一串二进制字节流就可以了。下面来了

荒野孤鹰 5987
上一篇: MySQL 自学重点笔记分享 - 事务&锁
下一篇: 面试官:spring事务失效有几个原因? 9个!解释一下?我傻了!
XingXing_Java
博客等级 码龄7年 278粉丝 89原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值