温故而知新,读懂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信息了

打开一个字节码文件,把各个部分用不同颜色标记起来,就如下图所示

参考

https://segmentfault.com/a/1190000037594434

posted on 2022-02-08 10:17  J.M.Liu  阅读(107)  评论(0编辑  收藏  举报