这一次,彻底弄懂 Java 字节码文件( 四 )


查找标志位为01,值为1的结构总表常量为CONSTANT_Utf8-info,length的占用2个字节十六进制为 00 01,那么length长度就是1(转换为十进制的值,即0 * 16的一次方 + 1),后面找到1个字节为61,通过HexFiend工具也能看到指向了a 。
所以,找到的十六进制:01 00 01 61
常量池中进一步印证下:
#6 = Utf8 I 十六进制字节码文件:
01 00 01 49 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65...
继续查找标志位为01,值为1的结构总表常量为CONSTANT_Utf8-info,length的占用2个字节十六进制为 00 01,那么length长度就是1,后面找到1个字节为49,通过HexFiend工具也能看到指向了I 。
所以,找到的十六进制:01 00 01 49
常量池中进一步印证下:
 #6 = Utf8 I十六进制字节码文件:
01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65...继续查找标志位为01,值为1的结构总表常量为CONSTANT_Utf8-info,length的占用2个字节十六进制为 00 06,那么length长度就是6(转换为十进制的值,即0 * 16的一次方 + 6),后面找到6个字节为 3C 69 6E 69 74 3E,通过HexFiend工具也能看到指向了<init> 。
所以,找到的十六进制:01 00 06 3C 69 6E 69 74 3E
常量池中进一步印证下:
#7 = Utf8 <init>以此类推,最终都能通过十六进制字节码并结合字节码结构总表分析在常量池中找到对应的字节码内容 。
 
4.4 访问标志访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final 。通过上面的MyTest1源代码,我们知道该文件是类并且是public的 。
Access_Flag访问标志结构表:

这一次,彻底弄懂 Java 字节码文件

文章插图
上述MyTest1类十六进制字节码中的位置:0x 00 21
这个 0x 00 21 是访问标志结构表中的 0x 00 20 和 0x 00 01 的并集,表示 ACC_PUBLIC 与 ACC_SUPER 。
 public class com.dskj.jvm.bytecode.MyTest1...flags: ACC_PUBLIC, ACC_SUPER访问标志之后的是This Class Name,对应十六进制为 0x 00 03
在常量池项目类型中查找:
 #3 = Class #22 // com/dskj/jvm/bytecode/MyTest1This Class Name之后的是Super Class Name,对应十六进制为 0x 00 04
在常量池项目类型中查找:
  #4 = Class #23 // java/lang/ObjectInterfaces
接口包括两部分,第一个是interfaces_count(接口个数),第二部分interfaces(接口名) 。
当前这个类对应的十六进制:00 00 转换为十进制仍然是0,说明当前这个类是没有实现任何接口的 。
因此,这个interfaces接口表就不会再出现了 。如果接口数量interfaces_count大于等于1的话,那么这个interfaces接口表是存在的 。
 
4.5 字段表Fields
字段包括两部分,第一个是fields_count(字段个数),第二部分fields(字段名) 。
当前这个类对应的十六进制:00 01 转换为十进制值为1,说明这个类内部有一个字段 。
字段表集合
字段表用于描述类和接口中声明的变量 。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量 。
字段表结构:
这一次,彻底弄懂 Java 字节码文件

文章插图
第一个是access_flags访问标志符,如public、private、protected、final、abstract等等 。
第二个name_index和第三个descriptor_index两个构成一个字段结构的完整信息 。
attributes_count是字段的独有的信息,如果值是0,后面的attributes也就不存在了 。
具体结构示例:
当前类字段对应的十六进制如下所示:
 field_info {u2 access_flags; 0002u2 name_index; 0005u2 descriptor_index; 0006u2 attributes_counts; 0000attribute_info attributes[attributes_count];}0x0002在访问标志结构表中对应的是ACC_PRIVATE 。
名称索引 0x0005 与 描述符索引 0x0006 转换为十六进制为 5 和 6,从 常量池结构表中查找结果:
 #5 = Utf8 a#6 = Utf8 I附加属性的数量为0x0000,转换为十进制为0,后面的附加属性attributes也就不会出现了 。
 
4.6 方法表 00 03 // methods_count00 01 // access_flags00 07 // name_index00 08 // descriptor_index00 01 // attributes_count00 09 // attribute_name_index00 00 00 38 // attribute_length00 02 // 附加属性的 max_stacks00 01 // 附加属性的 max_locals00 00 00 0A // 附加属性的 code_length2A B7 00 01 2A 04 B5 00 02 B1 // code_lengthc长度的字节,具体执行的字节码指令00 00 00 02 00 0A 00 00 00 0A 00 02 00 00 00 06 00 04 00 08 00 0B 00 00 00 0C 00 01 00 00 00 0A 00 0C 00 0D 00 00 00 01 00 0E 00 0F 00 01 00 09 00 00 00 2F 00 01 00 01 00 00 00 05 2A B4 00 02 AC 00 00 00 02 00 0A 00 00 00 06 00 01 00 00 00 0B 00 0B 00 00 00 0C 00 01 00 00 00 05 00 0C 00 0D 00 00 00 01 00 10 00 11 00 01 00 09 00 00 00 3E 00 02 00 02 00 00 00 06 2A 1B B5 00 02 B1 00 00 00 02 00 0A 00 00 00 0A 00 02 00 00 00 0F 00 05 00 10 00 0B 00 00 00 16 00 02 00 00 00 06 00 0C 00 0D 00 00 00 00 00 06 00 05 00 06 00 01 00 01 00 12 00 00 00 02 00 13


推荐阅读