JVM工作原理与实战(六):类的生命周期-连接阶段
专栏导航
JVM工作原理与实战
RabbitMQ入门指南
从零开始了解大数据
目录
专栏导航
前言
一、类的生命周期
1.加载(Loading)
2.连接(Linking)
3.初始化(Initialization)
4.使用(Using)
5.卸载(Unloading)
二、连接阶段
1.验证
2.准备
3.解析
总结
前言
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了类的生命周期、类的连接阶段等内容。
一、类的生命周期
类的生命周期描述了一个类加载、连接、初始化、使用、卸载的整个过程。
1.加载(Loading)
加载阶段是类的生命周期的起始点。当应用程序首次需要使用某个类时,Java虚拟机(JVM)会负责加载这个类。加载是通过类的加载器(ClassLoader)完成的,它会查找并加载类的二进制数据。这个过程包括将类的字节码从文件系统、JAR文件或网络加载到内存中。
2.连接(Linking)
连接阶段是加载阶段的后续,它包括验证、准备和解析三个子阶段。
- 验证(Verification):验证阶段主要是确保被加载的类文件数据符合JVM规范,没有安全方面的隐患,以及是否与应用程序的其它部分兼容。验证过程包括文件格式验证、元数据验证、字节码验证和符号引用验证。
- 准备(Preparation):准备阶段是为类的静态变量分配内存,并设置默认的初始值。需要注意的是,准备阶段并不会执行任何初始化操作。
- 解析(Resolution):解析阶段是将符号引用转换为直接引用。在Java中,符号引用是一个类的全限定名,而直接引用是一个直接指向内存中的地址的指针。解析阶段发生在运行时,而不是编译时。
3.初始化(Initialization)
初始化阶段是类加载过程中的最后一步,当准备和解析阶段完成后,JVM会执行类的构造器方法,这个方法是由编译器自动收集类中的所有类变量的赋值动作和静态代码块集合来的。需要注意的是,构造器方法中的代码只在类被首次使用时执行一次。
4.使用(Using)
一旦类被成功加载、连接并初始化后,就可以被实例化并用于执行应用程序的业务逻辑。在应用程序运行期间,类可能会被频繁地使用。
5.卸载(Unloading)
当应用程序不再需要某个类时,该类的实例以及与其相关的资源将会被回收,这个过程就是卸载。但是需要注意的是,只有当一个类不再被任何活动对象所引用时,它才会被卸载。另外,JVM的垃圾回收机制(Garbage Collection, GC)负责自动处理类的卸载和资源的回收。
二、连接阶段
1.验证
在Java类的生命周期中,连接阶段是一个至关重要的环节,它确保了Java字节码文件在被Java虚拟机(JVM)加载前满足一定的规范和要求。连接阶段的首要任务是验证,这一过程对Java字节码文件进行了严格的检查,以确保其遵守《Java虚拟机规范》中定义的各种约束。这一验证过程通常对程序员是透明的,不需要他们直接参与。
验证过程主要包括以下四个部分:
- 文件格式验证:这是验证的第一步,主要检查字节码文件的基本格式。例如,它会验证文件是否以特定的魔数(magic number)0xCAFEBABE开头,这是Java类文件的标识。此外,还会检查文件的主次版本号是否与当前Java虚拟机的版本兼容。版本号的检查是确保类文件是用与当前JVM兼容的Java编译器编译的。
- 元数据验证:在这一步中,验证器会检查类的元数据信息。这包括类的继承关系、接口实现、字段和方法的存在性和访问权限等。例如,验证器会确保每个类都有父类(除了java.lang.Object),并且类的继承层次结构没有出现问题。此外,还会检查方法的字节码,确保它们不会执行非法的操作,如跳转到不正确的位置。
- 字节码验证:这是最复杂的一步,验证器会深入分析方法的字节码,确保它们符合Java虚拟机的语义规则。这个过程会检查诸如类型安全、操作数栈的数据流和使用情况等。字节码验证的目的是防止潜在的恶意代码或由于编译器错误导致的无效代码被执行。
- 符号引用验证:在这一步中,验证器会检查类文件中的符号引用。符号引用是类在编译时对其他类、方法或字段的引用,这些引用在类加载时会被解析为实际的内存地址。验证器会确保这些符号引用是有效的,例如,不会访问其他类的私有方法或不存在的字段。
在Hotspot JDK 8的虚拟机源码中,版本号的检测是通过一段特定的代码来实现的。这段代码确保了主版本号(major version)和副版本号(minor version)都在Java虚拟机支持的范围内。具体来说,主版本号不能高于运行环境的主版本号,如果主版本号相等,则副版本号也不能超过运行环境所支持的最大副版本号。这样的版本号检测机制确保了类文件与运行环境的兼容性。
Hotspot JDK8中虚拟机源码对版本号检测的代码如下:
return (major >= JAVA_MIN_SUPPORTED_VERSION) && (major <= max_version) && ((major != max_version) || (minor <= JAVA_MAX_SUPPORTED_MINOR_VERSION));
major >= JAVA_MIN_SUPPORTED_VERSION | major(主版本号)大于或等于最小支持的Java版本 |
major <= max_version | major(主版本号)小于或等于最大支持的Java版本 |
(major != max_version) || (minor <= JAVA_MAX_SUPPORTED_MINOR_VERSION) | major(主版本号)不是最大支持版本,或者minor(次版本号)在最大支持范围内 |
验证阶段是Java类加载过程中非常重要的一环,它确保了只有符合规范的类文件才能被Java虚拟机加载和执行。这一过程不仅增强了Java平台的安全性,还提高了代码的健壮性和可移植性。
2.准备
准备阶段的主要任务是为类的静态变量分配内存,并设置这些变量的初始值。准备阶段只会为静态变量赋予初始值,而不是最终的值。每一种基本数据类型和引用数据类型在准备阶段都有其特定的初始值。
以下是基本数据类型和引用数据类型的初始值列表:
数据类型 | 初始值 |
int | 0 |
long | 0L |
short | 0 |
char | ‘\u0000’ |
byte | 0 |
boolean | false |
double | 0.0 |
引用数据类型 | null |
这些初始值是Java虚拟机规范所规定的,它们在准备阶段被自动赋予给相应的静态变量。
然而,有一个特殊的情况需要注意,那就是被final修饰的基本数据类型的静态变量。在准备阶段,如果静态变量被final修饰,并且其值在编译时就已经确定,那么Java虚拟机将直接将该值赋给静态变量,而不是赋予初始值。这一特性使得被final修饰的静态变量在准备阶段就能获得其最终的值。
下面通过两个示例来说明这一点:
示例一(类Test包含一个普通的静态变量i):
public class Test {public static int i = 1;public static void main(String[] args) {}
}
对于这个示例,在准备阶段,静态变量i
会被赋予其初始值0,而不是最终值1,最终值1的赋值发生在初始化阶段。
示例二(类Test包含一个被final修饰的静态变量i):
public class Test {public static final int i = 1;public static void main(String[] args) {}
}
对于这个示例,在准备阶段,静态变量i
会被直接赋予其最终值1,因为它是一个编译时常量。这意味着在准备阶段完成后,静态变量i
就已经获得了其最终的值,而不需要等到初始化阶段。
在Java类的生命周期的连接阶段中,准备阶段是一个关键步骤,它负责为静态变量分配内存并设置初始值。对于被final修饰的静态变量,如果其值在编译时就已经确定,那么准备阶段将直接赋予其最终值。这一特性为Java程序员提供了一种优化静态变量初始化的手段。
3.解析
解析阶段作为连接阶段的一部分,其主要任务是将常量池中的符号引用转换为直接引用。
符号引用:
在Java字节码中,常量池用于存储各种常量,如字符串、类名等。这些常量在常量池中通过编号进行索引。在字节码文件中,这些索引被用作符号引用。例如,当我们在字节码中引用一个类时,实际上是通过一个在常量池中的索引来引用该类,这个索引被称为类符号引用。同样地,字段和方法的引用也是通过相应的符号引用来表示的。
直接引用:
与符号引用不同,直接引用是直接指向目标对象的指针或地址。这意味着直接引用是具体的、指向内存中的某个位置的地址。通过直接引用,JVM可以直接定位并访问目标对象,而不必通过一系列的索引和查找操作。
解析过程:
在解析阶段,JVM将常量池中的符号引用转换为直接引用,这一过程是由JVM自动完成的。JVM在解析阶段会遍历字节码中的指令,将遇到的符号引用替换为直接引用。这个过程涉及到在运行时解析符号引用,并获取目标对象的实际内存地址。
举个例子,如果字节码中有一个对某个类的字段的访问指令,那么在解析阶段,JVM会找到该字段的实际内存地址,并将该地址作为直接引用存储在相应的指令中。这样,当执行该指令时,JVM可以直接访问该字段,而不需要通过查找常量池来获取符号引用。
解析阶段是连接阶段中的关键环节之一,它确保了JVM能够高效地访问和操作目标对象。通过将符号引用转换为直接引用,JVM能够提高指令执行的速度并降低内存开销。这也是Java虚拟机实现高效运行的重要手段之一。
总结
JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了类的生命周期、类的连接阶段等内容,希望对大家有所帮助。
相关文章:

JVM工作原理与实战(六):类的生命周期-连接阶段
专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、类的生命周期 1.加载(Loading) 2.连接(Linking) 3.初始化(Initialization) 4.使用(Using&…...
【OCR】 - Tesseract OCR在Windows系统中安装
Tesseract OCR 在Windows环境下安装Tesseract OCR(Optical Character Recognition)通常包括以下几个步骤: 下载Tesseract 访问Tesseract的GitHub发布页面:https://github.com/tesseract-ocr/tesseract/releases找到适合你操作系…...

YOLOv8改进 | 损失函数篇 | SlideLoss、FocalLoss分类损失函数助力细节涨点(全网最全)
一、本文介绍 本文给大家带来的是分类损失 SlideLoss、VFLoss、FocalLoss损失函数,我们之前看那的那些IoU都是边界框回归损失,和本文的修改内容并不冲突,所以大家可以知道损失函数分为两种一种是分类损失另一种是边界框回归损失,上一篇文章里面我们总结了过去百分之九十的…...
计算机网络试题——填空题(附答案)
在OSI模型中,第一层是____________层。 答案:物理(Physical) TCP协议是一种_____________连接的协议。 答案:面向连接(Connection-oriented) IPv6地址的位数是____________。 答案:1…...

第二证券:股票私募仓位指数创近八周新高
1月8日,A股几大首要指数全线收跌,上证指数收于日内最低点2887.54点,间隔上一年5月份的阶段高点3418.95点现已跌去了15.54%。 不过,虽然商场仍未清晰止跌,私募基金们却现已进场“抄底”。私募排排网最新发布的私募仓位…...
35-javascript基础,引入方式;变量命名规范
html分为三部分;结构html,表现css,行为js;js就是javascript js包含三部分: ECMAScript:简称ES,ES5,ES6核心语法 DOM:获取和操作html元素的标准方法;BOM&am…...

笔试案例2
文章目录 1、笔试案例22、思维导图 1、笔试案例2 09)查询学过「张三」老师授课的同学的信息 selects.*,c.cname,t.tname,sc.score from t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc where t.tidc.cid and c.cidsc.cid and sc.sids…...
【嵌入式-网络编程】vmware中使用UDP广播失败问题
问题描述: 自己在vmware中搭建了2台虚拟机,虚拟机A向虚拟机A和虚拟机B发送广播信息,接收端在虚拟机A和虚拟机B,这个时候,由于没配置sin.sin_addr.s_addr htonl(INADDR_ANY);,而是配置的inet_pton(AF_INET,…...

2020年认证杯SPSSPRO杯数学建模D题(第二阶段)让电脑桌面飞起来全过程文档及程序
2020年认证杯SPSSPRO杯数学建模 D题 让电脑桌面飞起来 原题再现: 对于一些必须每天使用电脑工作的白领来说,电脑桌面有着非常特殊的意义,通常一些频繁使用或者比较重要的图标会一直保留在桌面上,但是随着时间的推移,…...

vue3 修饰符大全(近万字长文)
系列文章目录 TypeScript 从入门到进阶专栏 文章目录 系列文章目录前言一、事件修饰符(Event Modifiers)1、.stop(阻止事件冒泡)2、.prevent(阻止事件的默认行为)3、.capture(使用事件捕获模式…...

HarmonyOS@State装饰器:组件内状态
State装饰器:组件内状态 State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。 在状态变量相关装饰器中,State是最基础的&…...

如何让GPT支持中文
上一篇已经讲解了如何构建自己的私人GPT,这一篇主要讲如何让GPT支持中文。 privateGPT 本地部署目前只支持基于llama.cpp 的 gguf格式模型,GGUF 是 llama.cpp 团队于 2023 年 8 月 21 日推出的一种新格式。它是 GGML 的替代品,llama.cpp 不再…...

使用开源通义千问模型(Qwen)搭建自己的大模型服务
目标 1、使用开源的大模型服务搭建属于自己的模型服务; 2、调优自己的大模型; 选型 采用通义千问模型,https://github.com/QwenLM/Qwen 步骤 1、下载模型文件 开源模型库:https://www.modelscope.cn/models mkdir -p /data/…...
Java工程师面试题解析与深度探讨
Java工程师面试题解析与深度探讨 第一部分:引言 Java作为一门广泛应用的编程语言,拥有庞大的生态系统,Java工程师因此成为众多企业追逐的目标。而在Java工程师的招聘中,面试是了解候选人技能和经验的核心环节。本文将深入探讨一…...

Linux下安装JET2
0. 说明: JET2是一个基于Joint Evolutionary Trees的利用序列和结构信息预测蛋白质界面的软件,详情见: http://www.lcqb.upmc.fr/JET2/JET2.html,http://www.lgm.upmc.fr/JET/JET.html 和 https://doi.org/10.1371/journal.pcbi.1004580 本…...
【PostgreSQL】表管理-表继承
PostgreSQL 表继承 PostgreSQL 实现了表继承,这对于数据库设计人员来说是一个有用的工具。(SQL:1999 及更高版本定义了类型继承功能,该功能在许多方面与此处描述的功能不同。 让我们从一个例子开始:假设我们正在尝试…...

Dijkstra算法——邻接矩阵实现+路径记录
本文是在下面这篇文章的基础上做了一些补充,增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。 [jarvan:Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎 https://zhuanlan.zhihu.com/p/338414118) …...
Vim基础操作
参考B站UP:正月点灯笼 vim入门教程(共3讲) 以下总结,部分搬运自评论区,楼主:-不是飞鱼QAQ,修改部分内容。 vim分为 命令 和 编辑 模式 i进入编辑模式( - - INSERT - - )…...

Mac上安装 Node.js 的版本管理工具 n,以及 n 使用,的使用
安装 最近刚更换 Mac 本进行项目的开发,刚上手 Mac 本还不是很熟练,需要安装 Node.js 的包管理工具 在 Windows 上我是实用的 nvm 来管理的 Node 版本,但是我尝试下载 Nvm ,发现下载安装后的 Nvm 无法使用,提示 “Th…...

Node.js和npm
目录 01_Node.js01.什么是 Node.js目标讲解小结 02.fs模块-读写文件目标讲解小结 03.path模块-路径处理目标讲解小结 04.案例-压缩前端html目标讲解小结 05.认识URL中的端口号目标讲解小结 06.http模块-创建Web服务目标讲解小结 07.案例-浏览时钟目标讲解小结 02_Node.js模块化…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...