JVM 类的加载过程详解

news2025/2/23 20:08:40

文章目录

  • 1. 哪些类需要加载
  • 2. 类加载步骤
    • 2.1 装载
      • 2.1.1 这个过程都做了什么事
      • 2.1.2 类的模板对象
      • 2.1.3 二进制流获取方式
      • 2.1.4 Class 实例的位置
      • 2.1.5 数组类的加载有什么不同
    • 2.2 链接
      • 2.2.1 验证
      • 2.2.2 准备
      • 2.2.3 解析
    • 2.3 初始化


在这里插入图片描述

在这里插入图片描述

1. 哪些类需要加载

在 Java 中数据类型分为 基本数据类型引用数据类型基本数据类型由虚拟机预先定义引用数据类型则需要进行类的加载。


2. 类加载步骤

类的加载步骤分为 : ①装载 ②链接 ③初始化

2.1 装载

所谓装载,简而言之就是将 Java 类的 字节码文件加载到机器内存中,并在内存中构建出Java类的原型——类模板对象。

2.1.1 这个过程都做了什么事

装载完成的操作

装载阶段,简言之,查找并加载类的二进制数据,生成Class的实例。

在加载类时,Java虚拟机必须完成以下3件事情:

  1. 通过类的全名,获取类的二进制数据流。
  2. 解析类的二进制数据流为方法区内的数据结构(Java类模型)。
  3. 创建 java.lang.Class 类的实例,表示该类型。作为方法区这个类的各种数据的访问入口。

2.1.2 类的模板对象

所谓类模板对象,其实就是Java类在JVM内存中的一个快照,JVM将从字节码文件中解析出的常量池、类字段、类方法等信息存储到类模板中,这样JVM在运行期便能通过类模板而获取Java类中的任意信息,能够对Java类的成员变量进行遍历,也能进行Java方法的调用。

反射的机制即基于这一基础。如果JVM没有将Java类的声明信息存储起来,则JVM在运行期也无法反射。

2.1.3 二进制流获取方式

对于类的二进制数据流,虚拟机可以通过多种途径产生或获得。(只要所读取的字节码符合 JVM 规范即可
● 虚拟机可能通过文件系统读入一个 .class 后缀的文件(最常见
● 读入 jar、zip 等归档数据包,提取类文件。
● 事先存放在数据库中的类的二进制数据。
● 使用类似于 HTTP 之类的协议通过网络进行加载。
● 在运行时生成一段 Class 的二进制信息等。

2.1.4 Class 实例的位置

类将 .class 文件加载至元空间后,会在堆中创建一个 Java.lang.Class 对象,用来封装类位于方法区内的数据结构,该 Class 对象是在加载类的过程中创建的,每个类都对应有一个Class类型的对象。(instanceKlass -->mirror :Class的实例)

举例:

在这里插入图片描述

外部可以通过访问代表 Order 类的 Class 对象来获取 Order 的类数据结构。

2.1.5 数组类的加载有什么不同

创建数组类的情况稍微有些特殊,因为 数组类本身并不是由类加载器负责创建,而是由 JVM 在运行时根据需要而直接创建的,但数组的元素类型仍然需要依靠类加载器去创建。

创建数组类(下述简称A)的过程:

  1. 如果数组的元素类型是引用类型,那么就遵循定义的加载过程递归加载和创建数组A的元素类型;
  2. JVM使用指定的元素类型和数组维度来创建新的数组类。
  3. 如果数组的元素类型是引用类型,数组类的可访问性就由元素类型的可访问性决定。否则数组类的可访问性将被缺省定义为public。

int[] arr
String[] arr
Object[] arr


2.2 链接

链接 分为三部分: 验证 准备 解析

2.2.1 验证

当类加载到系统后,就开始链接操作,验证是链接操作的第一步。

它的目的是保证加载的字节码是合法、合理并符合规范的。

验证的步骤比较复杂,实际要验证的项目也很繁多,大体上Java虚拟机需要做以下检査,如下图所示。

在这里插入图片描述
整体说明:

验证的内容则涵盖了类数据信息的格式验证、语义检查、字节码验证,以及符号引用验证等。

  • 其中格式验证会和装载阶段一起执行。验证通过之后,类加载器才会成功将类的二进制数据信息加载到方法区中。
  • 格式验证之外的验证操作将会在方法区中进行。

2.2.2 准备

简言之,为类的静态变量分配内存,并将其初始化为默认值。

在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置默认初始值。Java虚拟机为各类型变量默认的初始值如表所示。

在这里插入图片描述

注意:
这里不包含基本数据类型的用 static final 修饰的情况,因为 final 在编译的时候分配了,准备阶段会显示赋值。
在这个阶段并不会像初始化阶段中那样会有初始化或者代码被执行。

2.2.3 解析

简言之,将类、接口、字段和方法的符号引用转为直接引用。

1.具体描述:
符号引用就是一些字面量的引用,和虚拟机的内部数据结构和和内存布局无关。比较容易理解的就是在Class类文件中,通过常量池进行了大量的符号引用。但是在程序实际运行时,只有符号引用是不够的,比如当如下 println() 方法被调用时,系统需要明确知道该方法的位置。

举例:输出操作 System.out.println() 对应的字节码:
invokevirtual #24 <java/io/PrintStream.println>

在这里插入图片描述

以方法为例,Java虚拟机为每个类都准备了一张方法表,将其所有的方法都列在表中,当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法。通过解析操作,符号引用就可以转变为目标方法在类中方法表中的位置,从而使得方法被成功调用。

2.小结
所谓解析就是将符号引用转为直接引用,也就是得到类、字段、方法在内存中的指针或者偏移量。因此,可以说,如果直接引用存在,那么可以肯定系统中存在该类、方法或者字段。但只存在符号引用,不能确定系统中一定存在该结构。

不过Java虚拟机规范并没有明确要求解析阶段一定要按照顺序执行。在HotSpot VM中,加载、验证、准备和初始化会按照顺序有条不紊地执行,但链接阶段中的解析操作往往会伴随着JVM在执行完初始化之后再执行。


2.3 初始化

初始化阶段,简言之,为类的静态变量赋予正确的初始值。(显式初始化)


具体描述

类的初始化是类装载的最后一个阶段。如果前面的步骤都没有问题,那么表示类可以顺利装载到系统中。此时,类才会开始执行Java字节码。(即:到了初始化阶段,才真正开始执行类中定义的 Java 程序代码。
初始化阶段的重要工作是执行类的初始化方法:<clinit>()方法。

  • 该方法仅能由Java编译器生成并由JVM调用,程序开发者无法自定义一个同名的方法,更无法直接在Java程序中调用该方法,虽然该方法也是由字节码指令所组成。
  • 它是由类静态成员的赋值语句以及static语句块合并产生的。

在这里插入图片描述

  1. 子类加载钱先加载父类
    在加载一个类之前,虚拟机总是会试图加载该类的父类,因此父类的<clinit>总是在子类<clinit>之前被调用。也就是说,父类的 static 块优先级高于子类。
    口诀:由父及子,静态先行。

  2. 哪些类不会生成 <clinit> 方法
    Java编译器并不会为所有的类都产生 <clinit> ()初始化方法。哪些类在编译为字节码后,字节码文件中将不会包含 <clinit> ()方法?
    ● 一个类中并没有声明任何的类变量,也没有静态代码块时
    ● 一个类中声明类变量,但是没有明确使用类变量的初始化语句以及静态代码块来执行初始化操作时
    ● 一个类中包含 static final 修饰的基本数据类型的字段,这些类字段初始化语句采用编译时常量表达式

  3. 代码举例 static 与 final 搭配问题

  4. <clinit>() 的调用会死锁吗
    对于<clinit>()方法的调用,也就是类的初始化,虚拟机会在内部确保其多线程环境中的安全性。
    正是因为函数 <clinit>() 带锁线程安全的,因此,如果在一个类的()方法中有耗时很长的操作,就可能造成多个线程阻塞,引发死锁。并且这种死锁是很难发现的,因为看起来它们并没有可用的锁信息。

  5. 类的初始化情况(主动使用 被动使用)



在这里插入图片描述



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

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

相关文章

初始化linux数据盘(3TB)分区-格式化-挂载目录

场景说明&#xff1a;某云给我们服务器加载了一块3TB的硬盘扩容&#xff08;没有直接扩&#xff0c;原因是原来的盘做的是mbr&#xff08;什么年代了&#xff0c;谁干的&#xff09;的分区&#xff0c;最大识别2TB&#xff09; 确认磁盘 输入命令lsblk 查看数据盘信息 &#…

CEETRON SDK 可为您的CAE应用程序提供5大优势!

开发CAE应用程序是一项资源密集型、复杂且耗时的工作。成功的开发人员会尽其所能&#xff0c;确保他们专注于让他们的产品、他们的新想法独一无二的东西。凭借CEETRON系列产品及其集成的工具&#xff0c;Tech Soft 3D提供了唯一支持预处理、求解和后处理工作流程的完整CAE组件技…

PCIE协议-2-事务层规范-Completion Rules

2.2.9 完成规则 所有Read、Non-Posted Write和AtomicOp请求都需要完成&#xff08;Completion&#xff09;。完成包含一个完成头标&#xff0c;对于某些类型的完成&#xff0c;完成头标之后会跟随一定数量的DWs数据。完成头标的每个字段的规则在以下各节中定义。 完成通过ID路…

_remote.repositories作用

问题描述 明明我本地有某个依赖但是却还是报错&#xff0c;原因就是存在_remote.repositories且你的远程仓库中找不到该依赖&#xff0c;可能发生在你修改了远程仓库或镜像时。 例子 本地有这个依赖&#xff0c;但是报错。 解决 删除_remote.repositories文件&#xff0…

【多电压流程 Multivoltage Flow】- 5.特定工具使用建议(6.Formality)

使用Formality进行形式验证 Formality支持具有低功耗特性的功能等效性检查,如时钟门控、多阈值电压(multiple-Vt)、多电压供电、电源门控以及动态电压和频率缩放。Formality能够识别低功耗单元,例如隔离单元、电平转换器、始终开启单元、保持寄存器和电源门。 Formality支持…

微信小程序网格布局

效果图 实现 wxml <!-- 订单内容 --><view class"father"><!-- 订单item --><view class"childs" wx:for"{{List}}" wx:key"{{ index }}"></view></view> wxss .father{display: grid;grid-tem…

【二叉树】Leetcode 在每个树行中找最大值

题目讲解 515. 在每个树行中找最大值 算法讲解 这道题的重点在于怎么能够保存这一层的节点&#xff0c;并求出层节点的最大值&#xff1a;我们需要使用一个queue&#xff0c;每一次出队列的时候将当前队头结点的左右子树入队列&#xff08;这里就是将下一层的结点入队&#…

计算机Java项目|基于springboot的社区团购系统设计

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

vscode无法连接 , .vscode-server版本问题

vscode无法连接 &#xff0c; .vscode-server版本问题 解决办法 &#xff1a; 查看自己的版本号 2. 两边vscode版本号需要一致 找一台vscode可以远程连接的&#xff0c; 将它的.vscode-server/bin/b06ae3b2d2dbfe28bca3134cc6be65935cdfea6a 传到 远程服务器上 或者 本地的…

vue3组件插槽

Index.vue: <script setup> import { ref, onMounted } from vue import Child from ./Child.vue import ./index.cssonMounted(() > {}) </script><template><div class"m-home-wrap"><Child>插槽</Child><div class&qu…

1063 计算谱半径

solution 找出虚部和实部平方和的最大值&#xff0c;输出该最大值的开方&#xff0c;保留两位小数 #include<iostream> #include<cmath> using namespace std; int main(){int n, a, b, ans 0;scanf("%d", &n);while(n--){scanf("%d%d"…

安泰ATA-7050高压放大器应用领域:电流体动力喷墨打印技术!

柔性印刷电子器件性能强烈依赖于材料、线宽、以及工艺控制&#xff0c;实现高分辨率、高性能功能微纳结构的大面积、低成本、快速制造已经为柔性印刷电子产业化发展的基础性问题。与传统压电、热气泡等“挤”模式喷墨打印工艺不同&#xff0c;电流体喷墨打印&#xff08;Electr…

Unsupervised Image-to-Image Translation Networks

Unsupervised Image-to-Image Translation Networks 无监督图像到图像翻译网络 Ming-Yu Liu, Thomas Breuel, Jan Kautz 刘明玉&#xff0c;Thomas Breuel&#xff0c;Jan Kautz NVIDIA {mingyul,tbreuel,jkautz}nvidia.com NVIDIA {mingyul&#xff0c;tbreuel&#xff0c;j…

电动汽车与 PLM:下一代转型的结合

汽车电气化是汽车行业持续变革的驱动力&#xff0c;因此电动汽车 (EV) 行业成为当今最令人兴奋、最相关和最必要的创新领域之一。快速且有利可图地设计电动汽车及其零部件&#xff0c;同时使其受到消费者的青睐&#xff0c;是一项艰巨的挑战。因此&#xff0c;电动汽车行业企业…

想要成为项目经理?先掌握这24条职场生存法则!

以下是项目经理的24条职场经验&#xff0c;这些经验涵盖了项目管理的各个方面&#xff0c;希望能对项目经理或有意成为项目经理的人有所启发。 1、明确目标&#xff1a;项目成功的关键在于明确的目标。在项目启动之初&#xff0c;确保所有利益相关者对项目目标有清晰、共同的…

[Algorithm][递归][搜索][回溯]总体理解+ 算法总结 (极其干货哦~)

目录 0.观前必读1.递归1.什么是递归&#xff1f;2.为什么会用到递归&#xff1f;3.如何理解递归&#xff1f;4.如何写好一个递归&#xff1f; 2.概念乱斗:P1.深度优先遍历 vs 深度优先搜索 && 宽度优先遍历 vs 宽度优先搜索2.搜索 vs 暴搜3.拓展搜索问题 3.回溯与剪枝4…

PostgreSQL建表语句 INT, INT2, INT4, INT8 分别对应Java,Go, Python什么数据类型?

&#x1f42f; PostgreSQL建表语句 INT, INT2, INT4, INT8 分别对应Java&#xff0c;Go, Python什么数据类型 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题…

selenium进行xhs图片爬虫:06xhs一个博主的全部文章图片爬取

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️感谢大家点赞&#x1f44d;&…

计算机毕业设计源码 | 基于SpringBoot的线上教学系统 答疑辅导网站(附源码)

1&#xff0c;项目介绍 1.1 项目背景 网络问答平台经历了多年的发展&#xff0c;目前处于一个日益成熟的状态。最早的网络问答平台是知乎&#xff0c;知乎的创立者认为有许多信息在互联网上没有被记录和共享&#xff0c;于是他们决定创造一个平台&#xff0c;能够让更多人可以…

Spring的IOC和AOP机制?

我们是在使用Spring框架的过程中&#xff0c;其实就是为了使用IOC&#xff0c;依赖注入&#xff0c;和AOP&#xff0c;面向切面编程&#xff0c;这两个是Spring的灵魂。 主要用到的设计模式有工厂模式和代理模式。 IOC就是典型的工厂模式&#xff0c;通过sessionfactory去注入…