【JVM学习笔记03】类文件结构

【该章节主要总结了比较重要的部分,没有进行全面总结,后续将结合实际情况再继续补充完善】

四、类文件结构

我们平时说的 Java 字节码,指的是用 Java 语言编译成的字节码。准确的说任何能在 JVM 平台上执行的字节码格式都是一样的。所以应该统称为:JVM 字节码。

不同的编译器,可以编译出相同的字节码文件,字节码文件也可以在不同的 JVM 上运行。

Java 虚拟机与 Java 语言并没有必然的联系,它只与特定的二进制文件格式— Class 文件格式所关联,Class 文件中包含了 Java 虚拟机指令集(或者称为字节码、Bytecodes)和符号表,还有一些其他辅助信息。

image-20201110094949223

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎都是程序运行时必要的数据。

  • 魔数:每个Class文件的头4个字节被称为魔数。它的唯一作用是确定这个文件是否为一个能够被虚拟机接受的Class文件。使用魔数而不是扩展名来进行识别主要是基于安全考虑,因为文件的扩展名可以随意更改。Java的魔数名为“cafe babe”
  • 版本号:紧接着魔数存储的是Class文件的版本号、次版本号、主版本号。Java的版本号是从45开始的,JDK 1.1 之后每个JDK的主版本号加1,高版本的JDK能够向下兼容以前版本的Class文件
  • 常量池:常量池是Class文件里的资源仓库,是Class文件结构中与其他项目关联最多的数据。其中主要存储两大种常量:字面量和符号引用

4.1 类文件结构

Class文件是一组以8个字节为基础单位的二进制流(可能是磁盘文件,也可能是类加载器直接生成的),各个数据项目严格按照顺序紧凑地排列,中间没有任何分隔符;Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,其中只有两种数据类型:无符号数和表;

  • 无符号数属于基本的数据类型,以u1、u2、u4和u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值;
  • 表是由多个无符号数获取其他表作为数据项构成的复合数据类型,习惯以“_info”结尾;

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

image-20210813101854805

4.1.1 魔数与Class版本

Class文件的头4个字节,唯一作用是确定文件是否为一个可被虚拟机接受的Class文件,固定为“0xCAFEBABE”。

第5和第6个字节是次版本号,第7和第8个字节是主版本号(0x0034为52,对应JDK版本1.8);Java的版本号是从45开始的,JDK1.1之后的每一个JDK大版本发布主版本号向上加1,高版本的JDK能向下兼容低版本的JDK。

image-20210813101940754

4.1.2 常量池

紧接着主版本号的就是常量池,常量池可以理解为class文件的资源仓库,它是class文件结构中与其它项目关联最多的数据类型,也是占用class文件空间最大的数据项目之一,也是class文件中第一个出现的表类型数据项目。

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

常量池中主要存放两大类常量:字面量和符号引用。字面量比较接近Java语言的常量概念,如文本字符串、声明为final的常量等。而符号引用则属于编译原理方面的概念,它包括三方面的内容:

  • 类和接口的全限定名(Fully Qualified Name);
  • 字段的名称和描述符(Descriptor);
  • 方法的名称和描述符;

Java代码在进行javac编译的时候并不像C和C++那样有连接这一步,而是在虚拟机加载class文件的时候进行动态连接。也就是说,在class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,虚拟机也就无法使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址中。

常量池中的每一项都是一个表,表的开始第一个字节是一个u1类型的tag,用来标识是哪一种常量类型。这14种常量类型所代表的含义如下:

image-20210813102328755

4.1.3 访问标志

常量池结束后紧接着的两个字节代表访问标志,用来标识一些类或接口的访问信息,包括:这个Class是类还是接口;是否定义为public;是否定义为abstract;如果是类的话,是否被声明为final等。具体的标志位以及含义如下表:

image-20210813102451407

4.1.4 索引集合

【后续将结合《深入理解Java虚拟机》继续完善相关内容】

4.1.5 字段表集合

4.1.6 方法表集合

4.1.7 属性表集合

4.2 字节码指令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我姓弓长那个张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值