JVM 的类文件结构

时间:2022-11-27 05:49:13
CLASS文件结构顺序(无符号字符和表组成):魔数→版本号→常量池→访问标志→类索引→父类索引→接口索引→字段表集合→方法表集合→属性表集合


魔数:
位于Class文件起始4字节:用于进行身份识别,通过虚拟机生成的Class文件魔数为0xCAFEBABE。


版本号:
总共4字节,前两字节表明次版本号,后两字节表明主版本号(即每个JDK大版本),主版本起始值为45(JDK1.1),
每个版本不能向上兼容可以进行向下兼容,兼容后主版本号会根据差值减少。部分示例如下:
jdk 次版本 主版本
JDK1.6.0_01 0x0000 0x0032
JDK1.7.0 0x0000 0x0033
JDK1.8.0 0x0000 0x0034


常量池:
因为常量池中常量(一种表结构)的数量是可变长的,所以前两字节(即9-10字节)表示常量的数量,且为了满足
后面不引用任何常量池的常量的要求,所以常量池容器的计数从1开始,范围是1~(2^64-1)。后面的常量的格
式是标志位(1字节)+数据结构(字节数取决于标志位)。如标志位为0x07,则数据结构为3字节,前一字节是标
志位,后两字节(name_index)表示常量类型索引位置。
各数据类型的结构表:
常量 属性 字节数 描述
CONSTANT_Utf8_info tag 1 值为1
length 2 UTF-8字符所占据的字节数
bytes 1 长度为前面的length,每个只占1字节
CONSTANT_Integer_info tag 1 值为3
bytes 4 高位优先存储int值
CONSTANT_Float_info tag 1 值为4
bytes 4 高位优先存储float值
CONSTANT_Long_info tag 1 值为5
bytes 8 高位优先存储long值
CONSTANT_Double_info tag 1 值为6
bytes 8 高位优先存储double值
CONSTANT_Class_info tag 1 值为7
bytes 2 指向全限定名常量项的索引
CONSTANT_String_info tag 1 值为8
index 2 指向字符串字面量的索引
CONSTANT_Fieldref_info tag 1 值为9
index 2 指向CONSTANT_Class_info的索引
index 2 指向CONSTATN_NameAndType_info的索引
CONSTANT_Methodref_info tag 1 值为10
index 2 指向CONSTANT_Class_info的索引
index 2 指向CONSTATN_NameAndType_info的索引
CONSTANT_InterfaceMethodref_info tag 1 值为11
index 2 指向CONSTANT_Class_info的索引
index 2 指向CONSTATN_NameAndType_info的索引
CONSTANT_NameAndType_info tag 1 值为12
index 2 指向该字段或方法名称常量项的索引
index 2 指向该字段或方法描述符常量项的索引


访问标志:
常量池结束后,后面的两个字节表示访问标志(access_flags),用于表明该类或接口的作用域,类型等。比如
public(0x0001)、final(0x0010)等可以通过或运算计算出访问标志的值存入CLASS文件中。
访问标志表:
标志名称 标志值
ACC_PUBLIC 0x0001
ACC_FINAL 0x0010
ACC_SUPER 0x0020
ACC_INTERFACE 0x0200
ACC_ABSTRACT 0x0400
ACC_SYNTHETIC 0x1000
ACC_ANNOTATION 0x2000
ACC_ENUM 0x4000

类索引:
类索引紧随其后占据2字节。类索引通过指向常量池的常量项(CONSTANT_Class_info),用于确定该类的全限定名。


父类索引:
父类索引在类索引之后,占据2字节。父类索引表示该类的继承关系,除了Object是无父类索引(0x0000),
其他均指向常量池的常量项(CONSTANT_Class_info)。


接口索引集合:
接口索引集合在父类索引之后,同样占据2字节。其值表示的是接口数量(n),后面跟着n个2字符指向常量池
(CONSTANT_Class_info)的索引。


字段表集合:
该表结构无固定长度。用于描述类或接口中声明的变量。用于描述名称,类型等。
字段表结构:
名称 类型 数量 描述
access_flag 2字节 1 同上面的访问标志
name_index 2字节 1 指向该字段的简单名称的索引,(即声明的变量名)
descriptor_index 2字节 1 指向描述符的索引(描述符对应见下表)
attributes_count 2字节 1 附加属性的长度
attributes attribute_info attributes_count 每个字符占据字节数根据自定义的属性确定,详见属性表

描述符标识字符含义:
标识字符 对应类型
B byte
C char
D double
F float
I int
J long
S short
Z boolean
V void
L 对象类型
(  注:数组类型有特殊方式表示,如String[][]可以用[[Ljava/Lang/String   )

方法表集合:
和字段表集合类似,只是在access_flage上有不同。

属性表集合:
属性表没有严格的顺序、长度等,编译器自身定义属性的数据结构。
虚拟机规范预定义的部分属性:
属性名称 使用位置
Code 方法表
ConstatnValue 字段表
Deprecated 类、方法表、字段表
Exceptions 方法表
InnerClasses 类文件
LineNumberTable Code属性
LocalVariableTable Code属性
SourceFile 类文件
Synthetic 类、方发表、字段表
(注:JVM1.7规范中定义了21个属性项)


(注:JVM书上的u1、u2、u4、u8等分别表示在class文件中是1字节、2字节、4字节、8字节)