分析一个java class文件
虽然现在class文件可以直接通过 javap -verbose命令行来直接看结构清晰的class文件,也可以通过jclasslib这种idea的插件来通过有ui交互的方式来查看,但是分析一个class文件,有助于帮我们更好的了解class文件的结构,下面是要分析的class文件的java代码:
package com.example.jvm;
public class Test {
private int age = 99;
public static void main(String[] args) {
System.out.println("hello world");
}
}
编译成Test.class文件后,我们以16进制的方式打开,数据如下:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
00 01 00 0C 00 00 00 37 00 02 00 01 00 00 00 09
B2 00 03 12 04 B6 00 05 B1 00 00 00 02 00 0D 00
00 00 0A 00 02 00 00 00 08 00 08 00 09 00 0E 00
00 00 0C 00 01 00 00 00 09 00 13 00 14 00 00 00
01 00 15 00 00 00 02 00 16
class文件的结构如下(java8虚拟机规范中查询):
ClassFile {
u4 magic; //魔数
u2 minor_version; //副版本号
u2 major_version; //主版本号
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
4个字节的魔数
CA FE BA BE
接下来是2个字节的副版本号和2个字节的主版本号,他们共同构成了class文件的格式版本号
CA FE BA BE 00 00 00 34
可以看出副版本号是0,主版本号是52
接下来是两个字节的常量池计数器(constant_pool_count),constant_pool_count的值等于常量池中的成员数加1。
CA FE BA BE 00 00 00 34 00 26
0x0026 转为10进制是38,所以常量池中的成员数是 37。
然后是常量池数组的解析constant_pool,常量池中的每个值是由一个字节的tag,然后根据tag得到具体的数据结构来进行解析的,我们先读取常量池中的第一个字节,下面是tag表对应的关系:
类型 | 标志 | 描述 |
---|---|---|
CONSTANT_utf8_info | 1 | UTF-8编码的字符串 |
CONSTANT_Integer_info | 3 | 整形字面量 |
CONSTANT_Float_info | 4 | 浮点型字面量 |
CONSTANT_Long_info | 5 | 长整型字面量 |
CONSTANT_Double_info | 6 | 双精度浮点型字面量 |
CONSTANT_Class_info | 7 | 类或接口的符号引用 |
CONSTANT_String_info | 8 | 字符串类型字面量 |
CONSTANT_Fieldref_info | 9 | 字段的符号引用 |
CONSTANT_Methodref_info | 10 | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 12 | 字段或方法的符号引用 |
CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
CONSTANT_MothodType_info | 16 | 标志方法类型 |
CONSTANT_InvokeDynamic_info | 18 | 表示一个动态方法调用点 |
接下来我们读取读一个常量池的cp_info的值的tag是
CA FE BA BE 00 00 00 34 00 26 0A
0x0A的值十进制是10,可以得到该cp_info是CONSTANT_Methodref_info,结构如下
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
对应的十六进制里面的数据是
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 所以:
CONSTANT_Methodref_info {
u1 tag = 10;
u2 class_index = 7; // 常量池表的有效索引,数据接哦古为CONSTANT_Class_info
u2 name_and_type_index = 23;//常量池表的有效索引,对应的结构为CONSTANT_Fieldref_info,表示当前字段或方法的名字和描述符
}
index为2的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
所以具体的数据为:
CONSTANT_Fieldref_info {
u1 tag = 9;
u2 class_index = 6;
u2 name_and_type_index = 24;
}
index为3的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
所以具体数据为:
CONSTANT_Fieldref_info {
u1 tag = 9;
u2 class_index = 25;
u2 name_and_type_index = 26;
}
index为4的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
所以具体数据为:
CONSTANT_String_info {
u1 tag = 08;
u2 string_index = 27; //对应常量池中index为27的 CONSTATN_utf8_info的对象
}
index为5的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 01 00 01
所以具体数据为:
CONSTANT_Methodref_info {
u1 tag = 10;
u2 class_index = 28;
u2 name_and_type_index = 29;
}
index为6的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 01 00 01
所以具体数据为:
CONSTANT_Class_info {
u1 tag = 7;
u2 name_index = 30; //常量池中的索引,对应的结构为CONSTANT_Utf8_info,表示一个有效类名称的内部形式,例如com/example/jvm/Test
}
index为7的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 01 00 01
所以具体数据为:
CONSTANT_Class_info {
u1 tag = 7;
u2 name_index = 31;
}
index为8的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 01 00 01
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 3; //代表字符串的字节数
u1 bytes[length] = "age"; // (0x61, 0x67, 0x65) 代表字符串的字节数组
}
index为9的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 01 00 01
49 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 1; //代表字符串的字节数
u1 bytes[length] = "I"; //(0x49)
}
index为10的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 6;
u1 bytes[length] = "<init>";
}
index为11的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 36;
u1 bytes[length] = "()V";//方法签名,无参方法,无返回值
}
index为12的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 4;
u1 bytes[length] = "Code";
}
index为13的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 15;
u1 bytes[length] = "LineNumberTable"; //方法对应的行号
}
index为14的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 18;
u1 bytes[length] = "LocalVariableTable";//方法的局部变量表
}
index为15的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
所以具体数据为:
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 4;
u1 bytes[length] = "this";
}
index为16的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 22;
u1 bytes[length] = "Lcom/example/jvm/Test;"; //L是字段描述符L代表reference类型, I代表int 具体可以查java虚拟机规范的4.3.2章
}
index为17的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 4;
u1 bytes[length] = main;
}
index为18的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 22;
u1 bytes[length] = "([Ljava/lang/String;)V"; //[代表一维数组
}
index为19的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 4;
u1 bytes[length] = "args";
}
index为20的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 19;
u1 bytes[length] = "[Ljava/lang/String;";
}
index为21的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 10;
u1 bytes[length] = "SourceFile";
}
index为22的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 9;
u1 bytes[length] = "Test.java";
}
index为23的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
CONSTANT_NameAndType_info { //表示字段或者方法
u1 tag = 12;
u2 name_index = 10; //常量池中index为10的数据结构是 CONSTANT_Utf8_info 值为<init>
u2 descriptor_index = 11; //index为11的数据结构是CONSTATN_Utf8_info 值为 ()V
} //该类的构造方法
index为24的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
CONSTANT_NameAndType_info { //表示字段或者方法
u1 tag = 12;
u2 name_index = 8; //常量池中index为8的数据结构是CONSTANT_Utf8_info 值为age
u2 descriptor_index = 9; //index为9的数据格式是CONSTATN_Utf8_info 值为 I
} //该类的一个属性 属性名为age 类型是int
index为25的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
CONSTANT_Class_info {
u1 tag = 7;
u2 name_index = 32; // java/lang/System
}
index为26的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
CONSTANT_NameAndType_info {
u1 tag = 12;
u2 name_index = 33; // out
u2 descriptor_index = 34; // Ljava/io/PrintStream;
}
index为27的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 11;
u1 bytes[length] = "hello world";
}
index为28的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
CONSTANT_Class_info {
u1 tag = 7;
u2 name_index = 35; // java/io/PrintStream
}
index为29的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
CONSTANT_NameAndType_info {
u1 tag = 12;
u2 name_index = 36; // println
u2 descriptor_index = 37; // (Ljava/io/String;)V
}
index为30的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 20;
u1 bytes[length] = "com/example/jvm/Test";
}
index为31的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 16;
u1 bytes[length] = "java/lang/Object";
}
index为32的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 16;
u1 bytes[length] = "java/lang/System";
}
index为33的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 3;
u1 bytes[length] = "out";
}
index为34的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 21;
u1 bytes[length] = "Ljava/io/PrintStream;";
}
index为35的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 19;
u1 bytes[length] = "java/io/PrintStream";
}
index为36的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 7;
u1 bytes[length] = "println";
}
index为37的十六进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
CONSTANT_Utf8_info {
u1 tag = 1;
u2 length = 21;
u1 bytes[length] = "(Ljava/lang/String;)V";
}
到此常量池区的数据就解析完了,安装Java虚拟机规范的结构要求下面是 u2 access_flags:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
u2 access_flags = 0x21; //可以查java虚拟机规范表4-1 得知为ACC_PUBLIC | ACC_SUPER
接下来是 u2 this_class:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
u2 this_class = 0x06; //是常量池表中的一个有效索引值,查常量池表可得知是类Test的CONSTANT_Class_info数据
接下来是u2 super_class:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
u2 super_class = 0x07; //也是常量池中的一个索引,查常量池表可得知是类Object的CONSTANT_Class_info数据
再接下来是 u2 interfaces_count:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
u2 interfaces_count = 0x00; //接口计数器
由于 interfaces_count = 0;所以interfaces[]为空,接下来直接是fields_count:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
u2 fields_count = 0x01;
接下来是 field_info fields[fields_count],其中field_info的结构如下:
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
field_info {
u2 access_flags = 0x02; // ACC_PRIVATE
u2 name_index = 0x08; //常量池索引,查常量池可得为 age
u2 descriptor_index = 0x09; //常量池索引,查常量池可得为 I 代表int类型
u2 attributes_count = 0x00;
attribute_info attributes[attributes_count]; // 具体的结构可查java虚拟机规范
}
接下来是u2 methods_count:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
u2 methods_count = 0x02;
接下来是方法表,由methods_count=0x02可知方法表的大小为2,方法表的item method_info结构如下:
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
index为0的method_info的到attributes十六进制为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
method_info {
u2 access_flags = 0x01; //ACC_PUBLIC
u2 name_index = 10; // <init>
u2 descriptor_index = 11; //()V
u2 attributes_count = 1;
}
接下来是方法的attributes,我们首先先看一下attribute_info的数据结构:
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
所以方法的index为0的attribute到attribute_length的16进制数据为:
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
attribue_info {
u2 attribute_name_index = 12; // Code
u4 attribute_length = 57;
}
所以index为0的method_info的第一个属性为Code,Code属性的结构如下:
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
CA FE BA BE 00 00 00 34 00 26 0A 00 07 00 17 09
00 06 00 18 09 00 19 00 1A 08 00 1B 0A 00 1C 00
1D 07 00 1E 07 00 1F 01 00 03 61 67 65 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 00 12 4C 6F 63 61
6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00
04 74 68 69 73 01 00 16 4C 63 6F 6D 2F 65 78 61
6D 70 6C 65 2F 6A 76 6D 2F 54 65 73 74 3B 01 00
04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F
6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00
04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F
75 72 63 65 46 69 6C 65 01 00 09 54 65 73 74 2E
6A 61 76 61 0C 00 0A 00 0B 0C 00 08 00 09 07 00
20 0C 00 21 00 22 01 00 0B 68 65 6C 6C 6F 20 77
6F 72 6C 64 07 00 23 0C 00 24 00 25 01 00 14 63
6F 6D 2F 65 78 61 6D 70 6C 65 2F 6A 76 6D 2F 54
65 73 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F
4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61
6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74
53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69
6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07
70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61
2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
Code_attribute {
u2 attribute_name_index = 12;
u4 attribute_length = 57;
u2 max_stack = 2;
u2 max_locals = 1;
u4 code_length = 11;
u1 code[code_length] = ...;
u2 exception_table_length = 0;
}
因为code_length长度为11,我们需要往后数11个字节,为具体的操作指令:
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
第一个操作指令是0x2A,位于codes第0个字节下面的LineNumberTable中start pc有用 可以查操作指令的手册发现0x2A指令是aload_0 // 00|01 = 01,对应的是方法的引用
第二个操作指令是0xB7,codes[1] 是invokespecial 00, 01
第三个操作指令是0x2A,codes[4] 是aload_0
第四个操作指令是0x10, codes[5] 是bipush
第五个操作指令是0xB5,codes[7] 是putfield
第六个操作指令是0xB1,codes[10] 是return
接下来是两个字节的exception_table_length
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
Code_attribute {
u2 attribute_name_index = 12;
u4 attribute_length = 57;
u2 max_stack = 2;
u2 max_locals = 1;
u4 code_length = 11;
u2 exception_table_length = 0;
}
接下来是两个字节的attributes_count = 2
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
接下来是两个字节attributes,按照上面的结构直接可知第一个attribute为:
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
attribute {
u2 attribute_name_index = 13; //查常量池可知为 LineNumberTable
u4 attribute_length = 10;
}
LineNumberTable属性的结构如下:
LineNumberTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
{
u2 start_pc;
u2 line_number;
} line_number_table[line_number_table_length];
}
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
LineNumberTable_attribute {
u2 attribute_name_index = 13;
u4 attribute_length = 10;
u2 line_number_table_length = 2;
line_number_table[0] = {
u2 start_pc = 0; //对应的是上面code的所有,如 0 对应的是 aload_0
u2 line_number = 3; //java文件中的行号
};
line_number_table[1] = {
u2 start_pc = 4;
u2 line_number = 5;
};
}
接下来是第二个属性值:
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
attribute {
u2 attribute_name_index = 14; //查常量池可知为 LocalVariableTable
u4 attribute_length = 10;
}
LocalVariableTable的数据表结构为:
LocalVariableTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_table_length;
{
u2 start_pc;
u2 length;
u2 name_index;
u2 descriptor_index;
u2 index;
} local_variable_table[local_variable_table_length];
}
21 00 06 00 07 00 00 00 01 00 02 00 08 00 09 00
00 00 02 00 01 00 0A 00 0B 00 01 00 0C 00 00 00
39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 10 63
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
所以LocalVariableTable_attribute的数据为:
LocalVariableTable_attribute {
u2 attribute_name_index = 14;
u4 attribute_length = 12;
u2 local_variable_table_length = 1;
local_variable_table[0] =
{
u2 start_pc = 0;
u2 length = 11;
u2 name_index = 15; // this
u2 descriptor_index = 16; //Lcom/example/jvm/Test;
u2 index = 0;
};
}
至此<init>放方法的字节码就分析完了,我们把所有结构整合到一起:
method_info {
u2 access_flags = 0x01; //ACC_PUBLIC
u2 name_index = 10; // <init>
u2 descriptor_index = 11; //()V
u2 attributes_count = 1;
attributes = {
Code_attribute {
u2 attribute_name_index = 12;
u4 attribute_length = 57;
u2 max_stack = 2;
u2 max_locals = 1;
u4 code_length = 11;
codes = {
codes[0] : 0x2A; // aload_0
codes[1] = 0xB7; // invokespecial
codes[4] = 0x2A; // aload_0
codes[5] = 0x10; // bipush
codes[7] = 0xB5; // putfield
codes[10] = 0xB1; // return
};
u2 exception_table_length = 0;
u2 attributes_count = 2;
LineNumberTable_attribute {
u2 attribute_name_index = 13;
u4 attribute_length = 10;
u2 line_number_table_length = 2;
line_number_table[0] = {
u2 start_pc = 0; //对应的是上面code的所有,如 0 对应的是 aload_0
u2 line_number = 3; //java文件中的行号
};
line_number_table[1] = {
u2 start_pc = 4;
u2 line_number = 5;
};
}
LocalVariableTable_attribute {
u2 attribute_name_index = 14;
u4 attribute_length = 12;
u2 local_variable_table_length = 1;
local_variable_table[0] =
{
u2 start_pc = 0;
u2 length = 11;
u2 name_index = 15; // this
u2 descriptor_index = 16; //Lcom/example/jvm/Test;
u2 index = 0;
};
}
},
}
}
接下来就可以直接分析main方法了,main方法的分析过程跟<init>的过程是一样的,这里我们就一次性搞掉吧
B5 00 02 B1 00 00 00 02 00 0D 00 00 00 0A 00 02
00 00 00 03 00 04 00 05 00 0E 00 00 00 0C 00 01
00 00 00 0B 00 0F 00 10 00 00 00 09 00 11 00 12
00 01 00 0C 00 00 00 37 00 02 00 01 00 00 00 09
B2 00 03 12 04 B6 00 05 B1 00 00 00 02 00 0D 00
00 00 0A 00 02 00 00 00 08 00 08 00 09 00 0E 00
00 00 0C 00 01 00 00 00 09 00 13 00 14 00 00 00
01 00 15 00 00 00 02 00 16
method_info {
u2 access_flags = 0x09; //ACC_PUBLIC | ACC_STATIC
u2 name_index = 17; // main
u2 descriptor_index = 18; //([Ljava/lang/String;)V
u2 attributes_count = 1;
attributes = {
Code_attribute {
u2 attribute_name_index = 12;
u4 attribute_length = 55;
u2 max_stack = 2;
u2 max_locals = 1;
u4 code_length = 9;
codes = {
codes[0] = 0xB2; 0 (第几个字节 start pc有用) // getstatic (0x00 << 8) | (0x03) = 0x03;<java/lang/System.out>
codes[3] = 0x12; 3 // ldc 推送字符串到常量池 ldc 0x04(<Hello World>)
codes[5] = 0xB6; 5 // invokevirtual (0x00 << 8) | 0x05 = 0x05 //<java/io/PrintStream.println>
codes[8] = 0xB1; 8 // return
};
u2 exception_table_length = 0;
u2 attributes_count = 2;
LineNumberTable_attribute {
u2 attribute_name_index = 13;
u4 attribute_length = 10;
u2 line_number_table_length = 2;
line_number_table[0] = {
u2 start_pc = 0; //codes的索引 0 是 getstatic
u2 line_number = 8; //java文件中的行号
};
line_number_table[1] = {
u2 start_pc = 8;
u2 line_number = 9;
};
},
LocalVariableTable_attribute {
u2 attribute_name_index = 14;
u4 attribute_length = 12;
u2 local_variable_table_length = 1;
local_variable_table[0] =
{
u2 start_pc = 0;
u2 length = 9;
u2 name_index = 19; // args;
u2 descriptor_index = 20; //[Ljava/lang/String;
u2 index = 0;
};
}
},
}
}
接下来是u2 attributes_count = 1:
00 00 0A 00 02 00 00 00 08 00 08 00 09 00 0E 00
00 00 0C 00 01 00 00 00 09 00 13 00 14 00 00 00
01 00 15 00 00 00 02 00 16
00 00 0A 00 02 00 00 00 08 00 08 00 09 00 0E 00
00 00 0C 00 01 00 00 00 09 00 13 00 14 00 00 00
01 00 15 00 00 00 02 00 16
SourceFileAttribut {
u2 attribute_name_index = 21;//SoruceFile
u4 attribute_length = 2; // 2个字节
u2 sourcefile_index = 22; //Test.java
}
至此一个class文件分析完毕。