分析一个java class文件

分析一个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_info1UTF-8编码的字符串
CONSTANT_Integer_info3整形字面量
CONSTANT_Float_info4浮点型字面量
CONSTANT_Long_info5长整型字面量
CONSTANT_Double_info6双精度浮点型字面量
CONSTANT_Class_info7类或接口的符号引用
CONSTANT_String_info8字符串类型字面量
CONSTANT_Fieldref_info9字段的符号引用
CONSTANT_Methodref_info10类中方法的符号引用
CONSTANT_InterfaceMethodref_info11接口中方法的符号引用
CONSTANT_NameAndType_info12字段或方法的符号引用
CONSTANT_MethodHandle_info15表示方法句柄
CONSTANT_MothodType_info16标志方法类型
CONSTANT_InvokeDynamic_info18表示一个动态方法调用点

接下来我们读取读一个常量池的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文件分析完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值