JVM-9-Class类文件的结构

在这里插入图片描述
Java技术能够一直保持着非常良好的向后兼容性,Class文件结构的稳定功不可没。

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中。

Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:“无符号数”和“表”。

无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数。

表是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个Class文件本质上也可以视作是一张表。
在这里插入图片描述

无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时候称这一系列连续的某一类型的数据为某一类型的“集合”。

魔数与Class文件的版本

每个Class文件的头4个字节被称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。

Class文件的魔数取得很有“浪漫气息”,值为0xCAFEBABE(咖啡宝贝)。

紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节是次版本号(MinorVersion),第7和第8个字节是主版本号(Major Version)。

在这里插入图片描述

Java的版本号是从45开始的,JDK 1.1之后的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1使用了45.0~45.3的版本号)。

在这里插入图片描述

常量池

在这里插入图片描述

紧接着主、次版本号之后的是常量池入口,常量池可以比喻为Class文件里的资源仓库,它是Class文件结构中与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一。

由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值(constant_pool_count)。

这个容量计数是从1而不是0开始的,设计者将第0项常量空出来是有特殊考虑的,这样做的目的在于,如果后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的含义,可以把索引值设置为0来表示。

Class文件结构中只有常量池的容量计数是从1开始,对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都与一般习惯相同,是从0开始。

常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。

字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值等。

符号引用则属于编译原理方面的概念,主要包括下面几类常量:

  • 被模块导出或者开放的包(Package)
  • 类和接口的全限定名(Fully Qualified Name)
  • 字段的名称和描述符(Descriptor)
  • 方法的名称和描述符
  • 方法句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
  • 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)

在Class文件中不会保存各个方法、字段最终在内存中的布局信息,这些字段、方法的符号引用不经过虚拟机在运行期转换的话是无法得到真正的内存入口地址,也就无法直接被虚拟机使用的。当虚拟机做类加载时,将会从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。

常量表中分别有17种不同类型的常量。

在这里插入图片描述
使用javap命令输出常量表
在这里插入图片描述

访问标志

在常量池结束之后,紧接着的2个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口、是否定义为public类型、是否定义为abstract类型、如果是类的话,是否被声明为final等等。

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

类索引、父类索引与接口索引集合

类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引集合(interfaces)是一组u2类型的数据的集合,Class文件中由这三项数据来确定该类型的继承关系。

类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名。

对于接口索引集合,入口的第一项u2类型的数据为接口计数器(interfaces_count),表示索引表的容量。如果该类没有实现任何接口,则该计数器值为0,后面接口的索引表不再占用任何字节。
在这里插入图片描述

字段表集合

字段表(field_info)用于描述接口或者类中声明的变量,包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。

在这里插入图片描述字段访问标记
在这里插入图片描述

描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。根据描述符规则,基本数据类型(byte、char、double、float、int、long、short、boolean)以及代表无返回值的void类型都用一个大写字符来表示,而对象类型则用字符L加对象的全限定名来表示。
在这里插入图片描述
对于数组类型,每一维度将使用一个前置的“[”字符来描述,如一个定义为“java.lang.String[][]”类型的二维数组将被记录成“[[Ljava/lang/String;”,一个整型数组“int[]”将被记录成“[I”。

用描述符来描述方法时,按照先参数列表、后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号“()”之内。如方法void inc()的描述符为“()V”,方法java.lang.String toString()的描述符为“()Ljava/lang/String;”,方法int indexOf(char[]source,int sourceOffset,int sourceCount,char[]target,int targetOffset,int targetCount,int fromIndex)的描述符为“([CII[CIII)I”。

在这里插入图片描述
其值为0x0001,说明这个类只有一个字段表数据。接下来紧跟着容量计数器的是access_flags标志,值为0x0002,代表private修饰符的ACC_PRIVATE标志位为真(ACC_PRIVATE标志的值为0x0002),其他修饰符为假。代表字段名称的name_index的值为0x0005,从代码清单6-2列出的常量表中可查得第五项常量是一个CONSTANT_Utf8_info类型的字符串,其值为“m”,代表字段描述符的descriptor_index的值为0x0006,指向常量池的字符串“I”。根据这些信息,我们可以推断出原代码定义的字段为“private int m;”。

过在descriptor_index之后跟随着一个属性表集合,用于存储一些额外的信息,字段表可以在属性表中附加描述零至多项的额外信息。对于本例中的字段m,它的属性表计数器为0,也就是没有需要额外描述的信息,但是,如果将字段m的声明改为“final static int m=123;”,那就可能会存在一项名称为ConstantValue的属性,其值指向常量123。

方法表集合

Class文件存储格式中对方法的描述与对字段的描述采用了几乎完全一致的方式,方法表的结构如同字段表一样,依次包括访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)几项。
在这里插入图片描述
方法访问标志
在这里插入图片描述方法里的Java代码,经过Javac编译器编译成字节码指令之后,存放在方法属性表集合中一个名为“Code”的属性里面,属性表作为Class文件格式中最具扩展性的一种数据项目。

属性表集合

在这里插入图片描述
属性表(attribute_info)在前面的讲解之中已经出现过数次,Class文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何用idm下载迅雷 2024最新详细解析

有许多小伙伴日常习惯用迅雷处理或者下载文件,对于普通用户,由于迅雷平台的限速,下载速度仅有几十kb。此外,还有一些小伙伴安装idm后软件界面是英文,那么如何用idm下载迅雷,idm怎么设置中文呢?今…

Nginx+keepalived实现高可用负载群集

实现方式 使用Nginx作为负载调度器,通过四层代理转发给web器处理请求,实现负载均衡; 在Nginx调度器上配置脚本监控(健康检查),实现主备热备份,当主失效切换至备工作。 实验 实验准备 Web 服…

Linux 进程信号

文章目录 信号的概览信号的产生信号的处理信号集操作信号的捕捉补充与说明 信号的概览 信号由软件或硬件产生发送给进程,进程对其做相应处理。信号是进程之间事件异步通知的一种方式,属于软中断。 Linux下的全部信号由指令kill -l查询 Linux 下指令的…

SQL进阶理论篇(十):数据库中的锁

文章目录 简介按照锁的粒度进行划分从数据库管理的角度进行划分从程序员的角度进行划分为什么共享锁会发生死锁?参考文献 简介 索引和锁,是数据库中的两个核心知识点。 索引的相关知识点,在之前的几章里我们已经介绍的差不多了。接下来我们…

结构体基础例题

这里写目录标题 例题一例题解析答案 例题二例题解析答案 例题三例题解析答案 例题四例题解析答案 例题五例题解析及答案 例题六例题解析及答案 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒 个人主页 &#x1f978…

如何在大型Python项目中优雅地使用Dotenv

如何在大型Python项目中优雅地使用Dotenv 引言Dotenv的基本概念什么是Dotenv?Dotenv的工作原理如何在项目中使用Dotenv 环境变量与大型项目配置环境变量的重要性管理不同环境的配置使用Dotenv优化配置管理 Dotenv的高级应用动态配置与环境切换安全性和敏感数据管理与…

深入了解Linux信号:作用、产生、捕捉和阻塞

这里写目录标题 引言1. 信号的基本概念1.1 信号的分类和编号:1.2 查看信号默认处理动作1.3 信号的作用1.4 信号的产生1.4.1通过终端按键产生1.4.2通过系统函数向进程发信号1.4.3由软件条件产生信号1.4.4硬件异常产生信号 2. 常见信号及其作用SIGINT (2) - 中断信号&…

智慧水务系统解决了哪些问题

随着城市化进程的加快,水资源的日益紧缺和水环境问题的日益突出,传统的水务管理方式已经无法满足现代城市的需求。为了解决这些问题,智慧水务系统应运而生。 一、智慧水务系统概述 智慧水务系统是一种基于物联网、大数据、云计算等先进技术…

回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图)

回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图) 目录 回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图)效果一览基本介绍…

前端检测字符串中是否含有特殊字符,并返回该特殊字符

一、判断字符串中是否含有特殊字符 const hasSpecicalCharacter (str) > {var regex /[!#$%^&*(),.?":{}|<>]/return regex.test(str) } //含有特殊字符返回true, 没有特殊字符返回false 二、判断字符串中是否含有特殊字符&#xff0c;并返回该特殊字符…

作业--day32

机械臂 #include <myhead.h>#define PORT 8888 #define IP "192.168.125.59"int main(int argc, const char *argv[]) {int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd -1){perror("socket error");return -1;}int reuse -1;if(setsockopt(sfd…

C# 调用腾讯混元大模型

写在前面 今天用C#调用了一下腾讯混元大模型&#xff0c;调用代码贴一下&#xff0c;具体的效果等深入使用后再来评价。 GitHub - TencentCloud/tencentcloud-sdk-dotnet: Tencent Cloud API 3.0 SDK for .NET 腾讯混元大模型简介_腾讯混元大模型购买指南_腾讯混元大模型操作…

等保测评主要保护哪些方面的安全?

等保测评是经公安部认证的具有资质的测评机构&#xff0c;依据国家信息安全等级保护规范规定&#xff0c;受有关单位委托&#xff0c;按照有关管理规范和技术标准&#xff0c;对信息系统安全等级保护状况进行检测评估的活动。那么企业做等保“保”的是什么呢&#xff1f; 等保主…

直播江湖:东方甄选与董宇辉的权力游戏

出品| 大力财经 文 | 魏力 近期&#xff0c;围绕东方甄选的小作文事件引起了广泛关注&#xff0c;有人将其解读为一场巧妙策划的事件营销&#xff0c;然而&#xff0c;舆情的不可控性使得事态逐渐演变为一场复杂的利益博弈。 东方甄选与董宇辉的“蜜月期”可以说是双方互相成就…

直流电、交流电和发电机、接地、变压器

直流电 此节内容主要摘录自&#xff1a;图文详解直流电与直流电路基本知识 直流电是指电流方向不随时间作周期性变化&#xff0c;由正极流向负极&#xff0c;但电流的大小可能会变化的电流。直流电可以分为稳定&#xff08;恒定&#xff09;直流和脉动直流两种&#xff0c;如下…

Re解析(正则表达式解析)

正则表达式基础 元字符 B站教学视频&#xff1a; 正则表达式元字符基本使用 量词 贪婪匹配和惰性匹配 惰性匹配如下两张图&#xff0c;而 .* 就表示贪婪匹配&#xff0c;即尽可能多的匹配到符合的字符串&#xff0c;如果使用贪婪匹配&#xff0c;那么结果就是图中的情况三 p…

ZKP Commitment (1)

MIT IAP 2023 Modern Zero Knowledge Cryptography课程笔记 Lecture 5: Commitment 1 (Ying Tong Lai) Overview: Modern SNARK IOP: Interactive Oracle ProofCommitment SchemeIOP “compiled by” the commitment scheme to get a non-interactive proofAn IOP is “inform…

【重点】【前缀树|字典树】208.实现Trie(前缀树)

题目 前缀树介绍&#xff1a;https://blog.csdn.net/DeveloperFire/article/details/128861092 什么是前缀树 在计算机科学中&#xff0c;trie&#xff0c;又称前缀树或字典树&#xff0c;是一种有序树&#xff0c;用于保存关联数组&#xff0c;其中的键通常是字符串。与二叉查…

windows10-tdengine的安装及使用

win10-tdengine的安装及使用 一、下载及安装配置1.1 下载安装1.2 配置 二、启动及关闭服务2.1 启动tdengine服务2.2 关闭tdengine服务2.2 开机自启动配置 四、可视化工具&#xff08;GUI&#xff09;4.1 下载4.2 安装 五、TDengine 命令行&#xff08;CLI&#xff09;5.1 进入命…

st.pp.normalize_total(data) # NOTE: no log1p

这段代码在使用 stlearn 包中的 st.pp.normalize_total 函数对数据进行总体计数标准化。标准化后&#xff0c;每个细胞的总计数都将等于 median(total_counts)。 NOTE: no log1p 这行注释表示在标准化后&#xff0c;数据不会进行 log1p 转换。log1p 转换将每个计数值增加 1&a…