一、Class类文件结构
Class文件格式采用一种类似于C语言结构体的伪结构来储存数据,这种伪结构中只有两种数据类型:无符号数和表。
无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节,2个字节,4个字节,8个字节的无符号数。
表是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表都习惯性地以“_info”结尾。
魔数与Class文件的版本
每个Class文件的头4个字节称为魔术(Magic Number),它的唯一作用是确定整个文件是否为一个能被虚拟机接受的文件。其值为:0xCAFEBABE。
紧接着魔数的4个字节储存的是Class文件的版本号(Major Version):第5和第6个字节是次版本号(Minor Version),第7第8个字节是主版本号(Major Version)。
常量池
Class文件结构中只有常量池的容量计数是从1开始,其余都是从0开始。
常量池中主要存放两大类常量:字面量和符号引用。
字面量:接近于Java语言层面的常量概念,如文本字符串,声明为final的常量值等。
符号引用:类和接口的全限定命,字段的名称和描述符,方法的名称和描述符。
14种常量类型
每种类型的结构
读取常量时,先读取标志位,再判断常量类型,就能知道对应结构,获取对应的信息。
访问标志
在常量池结束之后,紧接着的两个字节代表访问标志(access_flags),用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义位public类型;是否定义为abstract类型;是否被声明为final等。
类索引、父类索引与接口索引集合
类索引用于确定这个类的全限定名
父类索引用于确定这个类的父类的全限定名
接口索引集合就用来描述这个类实现了哪些接口
Class文件中由这三项数据来确定这个类的继承关系。
字段表集合
字段表用于描述接口或者类中声明的变量。字段包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。
字段域开始的两个字节表示字段数量,之后为紧密排列的字段结构体顺序:
字段的简单名称(name_index):指没有类型和参数修饰的方法或者字段名称,如inc()方法和m字段的简单名称为“inc","m”。
方法和字段的描述符(descriptor_index):用来描述字段数据类型,方法的参数列表(包括数量,类型以及顺序)和返回值。用描述符描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号()之内。
方法表集合
方法表集合采用与字段表集合几乎完全一致的方式,唯一区别就是访问类型不完全一致。
属性表集合
Java 7中预定义的属性已增加到21项。
对于每个属性的结构,没有特别严格的要求,并且可以自定义属性信息,jvm运行时会忽略掉不认识的属性。
符合规范的属性表结构:
对于每个属性,它的名称需要从常量池中引用一个CONSTANT_info类型的属性名称,之后4个字节表示属性值所占用的位数,最后就是具体属性了。