各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码是构成平台无关性的基石。
1. Class类文件的结构
- Class文件是以8位字节为基础单位的二进制流,各个数据项紧凑地排列在Class文件中,没有任何分隔符。
- 采用类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表。
- 无符号数以u1、u2、u4、u8分别代表1,2,4,8个字节无符号数。可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成的字符串值。
- 表是由多个无符号数或者其他表作为数据项构成的复合数据类型。习惯性的以“_info”结尾。
- 魔数:每个Class文件的头4个字节。0xCAFEBABE
- Class文件的版本号:紧接着魔数的四个字节是Class文件的版本号,第5和6字节是次版本号,第7和8是主版本号。JDK7对应51.0
- 常量池:是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,也是Class文件中第一个出现的表类型数据项目。
常量池的入口放置一项u2类型的数据。代表常量池容量计数值(constant_pool_count)
- 常量池主要放两类常量:字面量和符号引用。字面量如文本字符串、声明为final的常量值等。符号引用包括:类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。
- 每一个常量都是一个表,JDK1.7共有14种表,表的第一位是一个u1类型的标志位。
常量池的项目类型
类型 | 标志 | 描述 |
CONSTANT_Utf8_info | 1 | UTF-8编码的字符串 |
CONSTANT_Integer_info | 2 | 整形 |
CONSTANT_Float_info | 3 | 浮点型 |
CONSTANT_Long_info | 4 | 长整型 |
CONSTANT_Double_info | 5 | 双精度型 |
CONSTANT_Class_info | 6 | 类或接口的符号引用 |
CONSTANT_String_info | 7 | 字符串类型 |
CONSTANT_Fieldref_info | 8 | 字段的符号引用 |
CONSTANT_Methodref_info | 9 | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 10 | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 11 | 字段或方法的部分符号应用 |
CONSTANT_MethodHandle_info | 12 | 表示方法句柄 |
CONSTANT_MethodType_info | 13 | 标识方法类型 |
CONSTANT_InvokeDynamic_info | 14 | 表示一个动态方法调用点 |
这14种常量类型均有自己的结构。1由tag(u1)、length(u2)、bytes(u1)组成;2-5有tag、bytes组成;6-11由tag、index(u2)、index组成。
- 访问标志:常量池结束之后,紧接着的两个字节代表访问标志。用于标识类或接口的访问信息。
- 类索引(u2)、父类索引(u2)、接口索引集合按顺序排在访问标志之后。类索引和父类索引分别指向一个类型为CONSTANT_Class_info的类描述符常量,对应一个全限定名字符串。接口索引集合
- 字段表集合:用于描述类中或接口中声明的变量,但不包括方法内部声明的变量。结构为access_flags(u2)、name_index(u2)、descriptor_index(u2)、attributes_count(u2)、attributes(类型:arrtibute_info 数量:attributes_count)。 全限定名是把类全名中的.换成/,比如“org/qr/edu/Test”;简单名称是方法或字段的名称比如getMax、count等;描述符作用是描述字段的数据类型、方法的参数列表、返回值,如“[[Ljava/lang/String”代表“java.lang.String[][]”类型的二维数组,“I[”代表整型数组“int[]”,“()Ljava/lang/String”为方法“java.lang.String toString”的描述符。
- 方法表集合:方法表的结构和字段表一样,含义也类似,仅在访问标志和属性表集合的可选项中有区别。方法里的代码经过编译器编译成字节码指令后,存放在方法属性表集合中一个名为“Code”的属性里面。重载方法时,需要有不同的特征签名。
- 属性表集合:Class文件、字段表、方法表都可以携带自己的属性表集合,用于描述某些场景专有的信息。属性表的结构应满足:attribute_name_index(u2)、attribute_length(u4)、info(类型:u1 长度:attribute_length)。java程序方法体重的代码经过Javac编译器处理之后,最终变成字节码指令存储在Code属性内。