1.定义一个测试类
public class MyTest1 {
private int a = 1;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
2.该类编译后产生的字节码文件。
MyTest1Code.jpg
3.反编译
执行 javap -verbose 类路径。
4.字节码结构图。
字节码文件结构图.jpg
一、魔数(Magic):0xCA 0xFE 0xBA 0xBE为固定值。
二、版本号(version):
0x00 0x00 0x00 0x34 对应 52对应 jdk1.8

f1.jpg

pool.jpg
四、常量池字节码演算
0x0A: 16进制为10 CONSTANT_methodref_info_tag: 值为16参照11种数据结构图找到对应的结构。
0x00 0x04: 指向声明方法的类索引项#4:// java/lang/Object
0x00 0x15:指向名称及类型的索引项#21:// "<init>":()V
0x09:CONSTANT_fieldref_info_tag 值为9参照11种数据结构图找到对应的结构。
0x00 0x03: 3 com/cucumber/cucumberexample/test/MyTest1
0x00 0x16: 22 #5:#6 // a:I
0x07:CONSTAN_class_info_tag
0x00 0x17:23 指向全限定名常量项索引。 //com/cucumber/cucumberexample/test/MyTest1
0x07:CONSTAN_class_info_tag
0x00 0x18:24 指向全限定名常量项索引: //java/lang/Object
0x01: CONSTANT_utf8_info_tag
0x00 0x01:表示真正内容的utf8编码长度,此处往后推1个字节码。
0x61 对应字符 a
0x01 :CONSTANT_utf8_info_tag
0x00 0x01:表示真正内容的utf8编码长度,此处往后推1个字节码。
0x49 对应字符 I
0x01:CONSTANT_utf8_info_tag
0x00 0x06:表示真正内容的utf8编码长度,此处往后推6个字节码。
0x3C 0x69 0x6E 0x69 0x74 0x3E:<init>
0x01:CONSTANT_utf8_info_tag
0x00 0x03:表示真正内容的utf8编码长度,此处往后推3个字节码。
0x28 0x29 0x56:()V
0x01:CONSTANT_utf8_info_tag
0x00 0x04:表示真正内容的utf8编码长度,此处往后推4个字节码。
0x43 0x6F 0x64 0x65:code
0x01:CONSTANT_utf8_info_tag
0x00 0x0F:表示真正内容的utf8编码长度,此处往后推15个字节码。
0x4C 0x69 0x6E 0x65 0x4E 0x75 0x6D 0x62 0x65 0x72
0x54 0x61 0x62 0x6C 0x65:LineNumberTable
0x01:CONSTANT_utf8_info_tag
0x00 0x12:表示真正内容的utf8编码长度,此处往后推18个字节码。
0x4C 0x6F 0x63 0x61 0x6C 0x56 0x61 0x72 0x69
0x61 0x62 0x6C 0x65 0x54 0x61 0x62 0x6C 0x65:LocalVariableTable
0x01:CONSTANT_utf8_info_tag
0x00 0x04:表示真正内容的utf8编码长度,此处往后推4个字节码。
0x74 0x68 0x69 0x73:this
0x01:CONSTANT_utf8_info_tag
0x00 0x2B:表示真正内容的utf8编码长度:此处往后推43个字节码。
0x4C 0x63 0x6F 0x6D 0x2F 0x63 0x75
0x63 0x75 0x6D 0x62 0x65 0x72 0x2F 0x63 0x75
0x63 0x75 0x6D 0x62 0x65 0x72 0x65 0x78 0x61
0x6D 0x70 0x6C 0x65 0x2F 0x74 0x65 0x73 0x74
0x2F 0x4D 0x79 0x54 0x65 0x73 0x74 0x31 0x3B://Lcom/cucmber/cucumberexample/test/MyTest1;
0x01:CONSTANT_utf8_info_tag
0x00 0x04:表示真正内容的utf8编码长度,此处往后推4个字节码。
0x67 0x65 0x74 0x41:getA()
0x01:CONSTANT_utf8_info_tag
0x00 0x03:表示真正内容的utf8编码长度:此处往后推3个字节码。
0x28 0x29 0x49:()I
0x01:CONSTANT_utf8_info_tag
0x00 0x04:表示真正内容的utf8编码长度,此处往后推4个字节码。
0x73 0x65 0x74 0x41:setA()
01:CONSTANT_utf8_info_tag
00 04:表示真正内容的utf8编码长度,此处往后推4个字节码。
67 65 74 41:getA()
0x01:CONSTANT_utf8_info_tag
0x00 0x04:表示真正内容的utf8编码长度,此处往后推4个字节码。
0x28 0x49 0x29 0x56:(I)V
0x01:CONSTANT_utf8_info_tag
0x00 0x10:表示真正内容的utf8编码长度,此处往后推16个字节码。
0x4D 0x65 0x74 0x68 0x6F 0x64 0x50
0x61 0x6D 0x65 0x74 0x65 0x72 0x73:MethodParameters
0x01:CONSTANT_utf8_info_tag
0x00 0x0A:表示真正内容的utf8编码长度,此处往后推10个字节码。
0x53 0x6F 0x75 0x72 0x63 0x65 0x46 0x69 0x6C 0x65 :SourceFile
0x01:CONSTANT_utf8_info_tag
0x00 0x0C:表示真正内容的utf8编码长度,此处往后推12个字节码。
0x4D 0x79 0x54 0x65 0x73 0x31 0x2E 0x6A 0x76 0x61 :MyTest1.java
0x0C:CONSTANT_nameAndType_info_tag
0x00 0x07:指向该字段方法名称常量索引项: <init>
0x00 0x08:指向该字段方法名称描述符常量索引项:()V
0C:CONSTANT_nameAndType_info_tag
0x00 0x05:指向该字段方法名称常量索引项: a
0x00 0x06:指向该字段方法名称描述符常量索引项:I
01:CONSTANT_utf8_info_tag
00 29:表示真正内容的utf8编码长度,此处往后推41个字节码
0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x75, 0x63, 0x75,
0x6D, 0x62, 0x65, 0x72, 0x2F, 0x63, 0x75, 0x63,
0x75, 0x6D, 0x62, 0x65, 0x72, 0x65, 0x78, 0x61,
0x6D, 0x70, 0x6C, 0x65, 0x2F, 0x74, 0x65, 0x73,
0x74, 0x2F, 0x4D, 0x79, 0x54, 0x65, 0x73, 0x74,
0x31://com/cucumber/cucumberexample/test/MyTest1
01:CONSTANT_utf8_info_tag
00 10:表示真正内容的utf8编码长度,此处往后推16个字节码
0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E,
0x67, 0x2F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74:java/lang/Objec
五、访问标示(access_flag):
访问标志符信息包括该class文件是类还是接口,是否被定义成public,是否是abstract如果是类,是否被声明成final.通过上面的源代码,我们知道该文件是类并且是public。

访问标志表.jpg
0x00, 0x21:0x21是0x20与0x01的合并,表示当前类的访问标志符为ACC_PUBLIC与ACC_SUPER。(参照访问标记表)
当前类索引(this_class):
0x00, 0x03:表示当前类引用常量池的索引:// com/cucumber/cucumberexample/test/MyTest1
父类索引(super_class):
0x00, 0x04:superClass引用常量池中的索引:// java/lang/Object
接口索引(interfaces):
0x00, 0x00: 00表示该类没有实现接口。
字段表(fields):
字段表结构:
filed_info{
u2 access_flags;0002
u2 name_index;0005
u2 descriptor_index;0006
u2 attribute_count;0000
u2 attribute_info attributes[attribute_count]
}
字段分析:
0x00, 0x01:表示该类只有1个字段。
0x00, 0x02:表示该字段的访问标识为ACC_PRIVATE。(参照访问标记表)
0x00, 0x05:表示该字段名称引用常量池索引为#5:a
0x00, 0x06:表示该字段名称描述符引用常量池索引为#6:I
方法表(methods):
0x00, 0x00, 0x00, 0x03:表示该类中有3个方法。
方法结构表:如下
方法结构表.jpg
0x00, 0x01:表示方法访问标示符为:public(参照访问标记表)
0x00, 0x07: 方法名称引用常量池的索引#7:<init>
0x00, 0x08:方法描述符引用常量池的索引#8:()V
0x00, 0x01:表示该方法中有1个属性。
0x00, 0x09:表示该方法属性引用常量池中的索引为9: //Code 就表示该方法的执行代码。
0x00, 0x00, 0x00, 0x38:表示该方法code的值占用56个字节。如下:
0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x2A, 0xB7,
0x00, 0x01, 0x2A, 0x04, 0xB5, 0x00, 0x02, 0xB1, 0x00, 0x00,
0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x02,
0x00, 0x00, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x0B,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A,
0x00, 0x0C, 0x00, 0x0D, 0x00, 0x00
接下来占用56个字节的Code值进行分析(参照Code结构表)。

code结构.jpg
构造方法:
0x00, 0x02:(max_stack)表示该方法最大操作栈的深度是2。
0x00, 0x01:(max_locals)表示该方法的局部变量的最大值为1。
0x00, 0x00, 0x00, 0x0A:(code_length)表示该方法所包含的字节码的字节数以及具体指令码。
0x0A等于16进制中的10,此处需要往后推10个字节。如下:
0x2A, 0xB7, 0x00, 0x01, 0x2A, 0x04, 0xB5, 0x00, 0x02, 0xB1
0x00, 0x00:(exception_table)异常表存放的是异常处理的信息,由于此方法没有异常所以为0。
0x00, 0x02:(attributes_count)表示该方法中存在2个属性,分别是0x00, 0x0A与0x00, 0x00。
LineNumberTable_attribute{ //LineNumberTable_info结构
u2 attribute_name_index;
u2 attribute_length;
u2 line_number_table_length;
{
u2 start_pc;
u2 line_number;
}line_number_table[line_number_table_length]
}
0x00, 0x0A:属性名称描述符引用常量池#10: LineNumberTable(参照LineNumberTable_info结构表)。
0x00, 0x00, 0x00, 0x0A:(u4 attributer_length)表示属性长度为10,需要往后推10个字节。如下:
0x00, 0x02:(表示2对映射),
0x00, 0x00, 0x00, 0x0A(字节码位置行号为0,映射到原代码偏移量为10),
0x00, 0x04, 0x00, 0x0C(字节码位置行号为4,映射到原代码偏移量为12)
LocalVariableTable_info{
u2 attrbute_name_index;
u4 attrbute_lenth;
u2 local_variable_table_length;
{
u2 start_pc;
u2 line_number;
}local_variable_table[local_variable_table_length]
}
0x00, 0x0B:属性名称描述符引用常量池#11:LocalVariableTable(参照LocalVariableTable_info结构表。
0x00, 0x00, 0x00, 0x0C:表示后面12个字节对应局部变量表的信息。如下:
0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x00
0x00, 0x01:表示局部变量的个数为1。
0x00, 0x00: 局部变量的开始位置为0。
0x00, 0x0A:局部变量的结束位置为10。
0x00, 0x0C:局部变量引用常量池中的索引为#12。//this
0x00, 0x0D:局部变量的描述引用常量池中的索引为#13。Lcom/cucumber/cucumberexample/test/MyTest1;
0x00, 0x00:用来进行校验检查。
-------------------------------------------------------------------------------------
get()方法分析:
0x00, 0x01:表示方法访问标示符为:public
0x00, 0x0E:方法名称引用常量池的索引#14:getA
0x00, 0x0F:方法描述符引用常量池的索引#15:()I
0x00, 0x01:表示该方法只有1个属性(参照方法属性表)
0x00, 0x09:方法名称引用常量池的索引#9: Code
0x00, 0x00, 0x00, 0x2F:表示该方法code的值占用47个字节(参照Code结构表)。如下:
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x2A, 0xB4,
0x00, 0x02, 0xAC, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x00,
0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x00,
0x05, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x00
0x00, 0x01:(max_stack)表示该方法最大操作栈的深度是1。
0x00, 0x01:(max_locals)表示该方法的局部变量的最大值为1。
0x00, 0x00, 0x00, 0x05:(code_length)表示该方法所包含的字节码的字节数以及具体指令码。如下:
0x2A(aload_0), 0xB4(getField),
0x00, 0x02(引用常量池中的索引#2。// com/cucumber/cucumberexample/test/MyTest1.a:I);
0xAC(ireturn:从方法中返回一个int类型的静态值。)
0x00, 0x00:(exception_table)异常表存放的是异常处理的信息,由于此方法没有异常所以为0。
0x00, 0x02:(attributes_count)表示该方法中存在2个属性,分别是0x00, 0x0A与0x00, 0x00。
0x00, 0x0A:属性名称描述符引用常量池#10: LineNumberTable(参照LineNumberTable_info结构表)。
0x00, 0x00, 0x00, 0x06(u4 attributer_length)表示属性长度为6,需要往后推6个字节。如下:
0x00, 0x01, 0x00, 0x00, 0x00, 0x0F
0x00, 0x01(表示1对映射),
0x00, 0x00, 0x00, 0x0F(字节码位置行号为0,映射到原代码偏移量为15)。
0x00, 0x0B:属性名称描述符引用常量池#11:LocalVariableTable(参照LocalVariableTable_info结构表。
0x00, 0x00, 0x00, 0x0C:表示后面12个字节对应局部变量表的信息。如下:
0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x00
0x00, 0x01:表示局部变量的个数为1。
0x00, 0x00: 局部变量的开始位置为0。
0x00, 0x05:局部变量的结束位置为5。
0x00, 0x0C:局部变量引用常量池中的索引为#12。this
0x00, 0x0D:局部变量的描述引用常量池中的索引为#13。Lcom/cucumber/cucumberexample/test/MyTest1;
0x00, 0x00:用来进行校验检查。
-------------------------------------------------------------------------
set()方法分析:
0x00, 0x01:表示方法访问标示符为:public
0x00, 0x10:方法名称引用常量池的索引#16: setA
0x00, 0x11:方法描述符引用常量池的索引#17:(I)V
0x00, 0x02:表示该方法中存在2个属性。
0x00, 0x09:方法名称引用常量池的索引#9: Code
0x00, 0x00, 0x00, 0x3E:表示该方法Code值占用62个字节。
如下:
0x00, 0x02, (max_stack)表示该方法最大操作栈的深度是2。
0x00, 0x02, (max_locals)表示该方法的局部变量的最大值为2。
0x00, 0x00, 0x00, 0x06, (code_length)表示该方法所包含的字节码的字节数以及具体指令码。如下:
0x2A, 0x1B, 0xB5, 0x00, 0x02, 0xB1,
0x00, 0x00,(exception_table)异常表存放的是异常处理的信息,由于此方法没有异常所以为0。
0x00, 0x02,(attributes_count)表示该方法中存在2个属性,分别是0x00, 0x0A与0x00, 0x00。
0x00, 0x0A, 属性名称描述符引用常量池#10: LineNumberTable(参照LineNumberTable_info结构表)。
0x00, 0x00, 0x00, 0x0A:u4 attributer_length)表示属性长度为10,需要往后推10个字节。如下:
0x00, 0x02:表示2对映射
0x00, 0x00, 0x00, 0x13:(字节码位置行号为0,映射到原代码偏第19行)。
0x00, 0x05, 0x00, 0x14:(字节码位置行号为5,映射到原代码偏第20行)。
0x00, 0x0B:属性名称描述符引用常量池#11:LocalVariableTable(参照LocalVariableTable_info结构表。)
0x00, 0x00, 0x00, 0x16:表示后面22个字节对应局部变量表的信息。如下:
0x00, 0x02:表示有2个局部变量。
0x00, 0x00:局部变量的开始位置为0。
0x00, 0x06:局部变量的结束位置为6。
0x00, 0x0C:局部变量引用常量池中的索引为#12。this
0x00, 0x0D:局部变量的描述引用常量池中的索引为#13。Lcom/cucumber/cucumberexample/test/MyTest1;
0x00, 0x00:局部变量的开始位置为0。
0x00, 0x06:局部变量的结束位置为6。
0x00, 0x05:局部变量引用常量池中的索引为#5。a
0x00, 0x06:局部变量的描述引用常量池中的索引为#6。I
七、附加属性(attributes):
attributes表结构:
attribute_info{
u2 attribute_name_index;
u4 attribute_length;
u1 info [attribute_length]
}
0x00, 0x01:表示当前文件有1个属性。
0x00, 0x13:指向常量池中的引用19。SourceFile
0x00, 0x00, 0x00, 0x02:占用2个字节。
0x00, 0x14:指向常量池中的引用20。 MyTest1.java