温故而知新,读懂java字节码
字节码只有两种结构:无符号数和表。整体结构如下表所示。
魔术
魔术是固定的,用十六进制表示为 cafebabe,用以表示这是一个java字节码。
版本号
版本号现代只用主版本号,此版本号全部为0. 在jdk12时期,此版本号被用作公测特性申明。
常量池
- 只有常量池的计数和序号从1开始,其他重复项的技术和需要还是从0开始的。
- 常量池中存放两大类常量:字面量和符号引用。
- 常量池中每一项都是一个表
- 常量池中的表结构,第一项都是tag,表示表的类型。
- 局部变量名、方法名、属性名,以及引用外部类方法名、Object上的一些东西,都会直接或间接把名字存到Utf8类型的表上。
访问标志
这是一个2字节的标记符,每一位上代表一个含义,如是否为public 、是否为final等等。
类索引、父类索引和接口索引集合
- 类索引和接口都是一个u2,表示常量池中的一个constant_class_info类型的表项。
- 接口索引是一个集合,现有一个u2表示接口数,后面有0-n个u2,表示各接口在常量池中的编号。
字段表集合
- 先有一个u2表示字段个数(包括类级变量和实例变量、但不包括局部变量)
- 后面跟0-n个field_info表。
- 每个field_info表先有一个u2控制符flag。再有一个u2字段简单名和一个u2字段描述符,都是表示到常量池的索引号。
- 字段描述表示字段类型,在常量池中。基本类似(int 、void等)用一个大写字母表示;对象类型用L加对象全限定名表示;数组类型使用一个前置的[符号表示;最后面还有一个属性表集合用以防止一些额外信息(如常量字段的值)。
- 字段表不会有继承的字段。
方法表集合
- 结构和字段表集合一样。但有些项的含义解析不一样:控制符flag的每一位含义不一样、在常量池中,描述符的格式是“(参数1类型参数2类型…)返回值”
- 方法表也不会有继承的方法。
- 方法体代码在后面的属性表集合中。
属性表集合
属性表集合在class文件、字段表、方法表中都可以出现。属性表是最复杂、扩展性最强的表结构。
- 最开始是一个u2表示属性名,表示属性表的类型,属性表虚拟机最开始只有9中属性,现在有29种。
- 接着是一个u4表示后面info信息的长度
- 最后就是Info信息了
打开一个字节码文件,把各个部分用不同颜色标记起来,就如下图所示