《深入理解JAVA虚拟机》--第六章 类文件结构

时间:2022-12-28 07:51:04

与平台无关性实现在操作系统的应用层,各种不同平台的虚拟机与所有平台都统一使用的程序存储格式--字节码是构成平台无关性的基石

实现语言无关性的基础是虚拟机和字节码存储格式,使用Java编译器可以把Java代码编译为存储字节码的Class文件,使用其他语言的编译器也可以相应编译成Class文件,其他语言也可以在JAVA虚拟机中运行,虚拟机不关心Class的来源,只有符合Class文件应有的结构就可以在JAVA虚拟机中运行。

Class类文件的结构

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

Class文件格式采用一种类似C炎炎结构题的伪结构来存储,这种结构只有两种数据类型:无符号数和表

无符号数,属于基本数据类型,以u1,u2,u4,8分别代表1个字节,2个字节,4个字节,8个字节的无符号数;无符号数可以用来描述数字,索引引用,数量值,或者按照UTF-8编码构成的字符串值。

表是由多个无符号数或其他表作为数据项构成的复合数据类型,习惯以_info结尾,用于描述有层次关系的符合结构的数据,整个Class文件本质上就是一张表


分析Class文件

1,头4个字节为魔数,用于确定这个文件是否为一个能被虚拟机接受的Class文件,值为:0xCAFEBABE

2,紧接着4个字节,5,6字节是次版本号,7,8字节是主版本号。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,即使文件格式并未发生变化。

3,紧接着主次版本号之后的是常量池入口,1,常量池是Class文件结构中与其他项目关联最多的数据类型,2,占用Class文件空间最大的数据项目之一,3,在Cass文件中第一个出现的表结构数据项目;常量池的前两个字节是一项u2类型的数据,代表常量池容量计数器。这个容量计数是从1开始而不是0,把第0项常量空出来是为了满足 后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”。

常量池主要两大类常量:字面量和符号引用,字面量类似Java语言的常量概念,如文本字符串,被声明final的常量值等,符号引用属于编译原理方面的概念

三类常量:类和接口的全限定名,字段的名陈和描述符,方法的名称和描述符

Java代码在javac编译时不会连接,而是在虚拟机加载Class文件进行动态连接,即在Class文件中不会保存各个方法和字段的最终内存布局信息

常量池的每一项常量都是一个表,共有11种不同结构的表结构数据,这11种表的共同特点就是,表开始的第一位是一个u1类型的标志位,代表当前这个常量属于哪种常量类型。

4,接着2个字节,代表访问标志,用于识别一些类或接口层次的访问信息

5,接着是类索引,父类索引和接口索引集合;类,父类索引是一个u2(2个字节)类型的数据,索引接口是一组u2类型的数据集合,Class文件由这三项数据来确定这个类的继承关系

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

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

接口索引集合用来描述这个类实现哪些接口

根据顺序判断子父类

6,字段表集合,用于描述接口或类中声明的变量

7,方法表集合,如字段表一样,包括发那个问标志,名称索引,描述符索引,属性表集合

8,属性表集合

Code属性,Java程序方法体里面的代码经过javac编译器处理之后,最终变为字节码指令存储在Code属性内。Code属性出现在方法表的属性集合之中,但有特殊,如接口或抽象类中的方法不存在Code属性。

Exceptions属性,列举出方法中可能抛出的受查异常,即方法描述时在throws关键字后面列举的异常。