class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,没有空隙和分隔符。当遇到需要占用8位以上的空间时,按照高位在前的方式分割成若干个8位字节存储。
class文件中只有两种数据类型:无符号数和表。
无符号属于基本的数据类型,以u1、u2、u4、u8来代表1个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串常量。
表是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表习惯性的以”_info“结尾。整个class文件本质就是一张表,由多个数据项构成:
魔数:u4,CAFEBABE
Class文件的版本号:u2次版本号,u2主版本号,java版本号从45开始。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,即使文件格式未发生改变,虚拟机也必须拒绝超过版本号的Class文件。
常量池:由于数量不固定,常量池前放置u2类型的数据,代表常量池计数值,这个容量计数值从1开始。设计者将0项常量空出来是为了满足后面某些指向常量池的索引值的数据在特殊情况下需要表达”不引用任何一个常量池项目“的含义。对于其他表类型都是从0开始。
常量池主要存放两大类常量:字面量和符号引用。字面量比较接近java语言层面的常量概念;而符号引用则属于编译原理方面的概念,包括一下三类常量:
- 类和接口的全限定名。
- 字段的名称和描述符。
- 方法的名称和描述符。
常量池中的每一项都是一个表,JDK1.7之前共有11中,JDK1.7增加了3种。这14种表的共同点是表的开始第一位是一个u1类型的标志位,代表当前常量属于哪一种常量类型。14种常量类型如下:
如标志为7为CONSTANT_Class_info,代表类或接口的符号引用,其结构如下:
tag是标志位,上面已经讲过,它用于区分常量类型。name_index是一个缩索引值,它指向常量池中一个Constant_utf8_info类型常量,此常量代表这个类的全限定名。
CONSTANT_UTF8_info类型的常量结构如下:
length说明这个U TF-8编码的字符串长度是多少个字节,它后面紧跟着长度为length字节的连续数据是一个使用UTF-8缩略编码表示的字符串。
javap分析Class文件字节码的工具 -verbose。
这14种常量项的数据结构定义如下:
访问标志:u2,这个标志用于识别类或接口层次的访问信息
类索引、父类索引与接口索引集合:。。。
字段表集合:用于描述接口或类中声明的变量。字段包括类级别变量以及实例变量,但不包含方法内部声明的局部变量。字段表结构如下:
方法表:。。。
属性表:。。。