Java虚拟机学习---Class文件解析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/u010838555/article/details/102768273

class文件整体结构: 

类型 名称    说明 长度
u4 magic 魔数,识别Class文件格式 4个字节
u2             minor_version 副版本号 2个字节
u2          major_version  主版本号  2个字节
u2            constant_pool_count 常量池计算器  2个字节
cp_info             constant_pool 常量池 n个字节
u2             access_flags 访问标志 2个字节
u2             this_class 类索引 2个字节
u2             super_class 父类索引 2个字节
u2           interfaces_count 接口计数器  2个字节
u2            interfaces 接口索引集合  2个字节
u2             fields_count 字段个数 2个字节
field_info          fields 字段集合 n个字节
u2            methods_count 方法计数器  2个字节
method_info    methods 方法集合 n个字节
u2             attributes_count 附加属性计数器 2个字节
attribute_info   attributes 附加属性集合   n个字节

   表中的u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成的字符串值。

Person类声明如下:

package build;

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "name:"+name+",age:"+age;
    }
}

Main类的声明如下:

package build;

public class Main {

    public static String TAG = "This is a tag";
    public static int mType = 1234;

    public static void main(String[] params) {
        Person person = new Person();
        person.setAge(18);
        person.setName("范冰冰");
        print(person);
    }

    public static void print(Person person) {
        System.out.println(person.toString());
    }
}

这里只解析Main类编译后的class文件---Main.class

使用javac Main.java命令编译后的class文件内容如下(因为使用javac 命令只能编译当前目录的文件,而Main对象引用了Person对象,会出现编译失败的问题,只需要编译上层文件夹即可 javac build/*。):

cafe babe 0000 0034 003a 0a00 0f00 1f07
0020 0a00 0200 1f0a 0002 0021 0800 220a
0002 0023 0a00 0e00 2409 0025 0026 0a00
0200 270a 0028 0029 0800 2a09 000e 002b
0900 0e00 2c07 002d 0700 2e01 0003 5441
4701 0012 4c6a 6176 612f 6c61 6e67 2f53
7472 696e 673b 0100 056d 5479 7065 0100
0149 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 046d 6169
6e01 0016 285b 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0100 0570 7269
6e74 0100 1128 4c62 7569 6c64 2f50 6572
736f 6e3b 2956 0100 083c 636c 696e 6974
3e01 000a 536f 7572 6365 4669 6c65 0100
094d 6169 6e2e 6a61 7661 0c00 1400 1501
000c 6275 696c 642f 5065 7273 6f6e 0c00
2f00 3001 0009 e88c 83e5 86b0 e586 b00c
0031 0032 0c00 1a00 1b07 0033 0c00 3400
350c 0036 0037 0700 380c 0039 0032 0100
0d54 6869 7320 6973 2061 2074 6167 0c00
1000 110c 0012 0013 0100 0a62 7569 6c64
2f4d 6169 6e01 0010 6a61 7661 2f6c 616e
672f 4f62 6a65 6374 0100 0673 6574 4167
6501 0004 2849 2956 0100 0773 6574 4e61
6d65 0100 1528 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0100 106a 6176
612f 6c61 6e67 2f53 7973 7465 6d01 0003
6f75 7401 0015 4c6a 6176 612f 696f 2f50
7269 6e74 5374 7265 616d 3b01 0008 746f
5374 7269 6e67 0100 1428 294c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 3b01 0013
6a61 7661 2f69 6f2f 5072 696e 7453 7472
6561 6d01 0007 7072 696e 746c 6e00 2100
0e00 0f00 0000 0200 0900 1000 1100 0000
0900 1200 1300 0000 0400 0100 1400 1500
0100 1600 0000 1d00 0100 0100 0000 052a
b700 01b1 0000 0001 0017 0000 0006 0001
0000 0003 0009 0018 0019 0001 0016 0000
0041 0002 0002 0000 0019 bb00 0259 b700
034c 2b10 12b6 0004 2b12 05b6 0006 2bb8
0007 b100 0000 0100 1700 0000 1600 0500
0000 0900 0800 0a00 0e00 0b00 1400 0c00
1800 0d00 0900 1a00 1b00 0100 1600 0000
2700 0200 0100 0000 0bb2 0008 2ab6 0009
b600 0ab1 0000 0001 0017 0000 000a 0002
0000 0010 000a 0011 0008 001c 0015 0001
0016 0000 0028 0001 0000 0000 000c 120b
b300 0c11 04d2 b300 0db1 0000 0001 0017
0000 000a 0002 0000 0005 0005 0006 0001
001d 0000 0002 001e 

下面解析里面的内容:

CA FE BA BE ----魔术,标识这是一个class文件。 

00 00 ----副版本号

00 34 ----主版本号:52,Java版本号从45(Java1.1)开始,每个大版本发布时,版本号加1,代表这个Class文件可以被JDK 1.8编译,高版本的JDK能向下兼容以前版本的Class文件。

00 3A ----常量池计数,代表有58个常量。它从1开始计数,代表这个Class文件中有57个常量,索引范围1~57。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 0F ----指向声明方法的类描述符CONSTANT_Class_info的索引项:15。

  00 1F ----指向名称及类型描述符CONSTANT_NameAndType的索引项:31。

07 ----7,说明这是一个类或接口的符号引用。根据它的表结构可知,接下的2个字节是它的内容。

  00 20 ----指向全限定名常量的索引:32。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 02 ----指向声明方法的类描述符CONSTANT_Class_info的索引项:2。

  00 1F ----指向名称及类型描述符CONSTANT_NameAndType的索引项:31。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 02 ----指向声明方法的类描述符CONSTANT_Class_info的索引项:2。

  00 21 ----指向名称及类型描述符CONSTANT_NameAndType的索引项:33。

08 ----8,说明这是字符串类型字面量,根据它的表结构可知,接下的2个字节是它的内容。

  00 22 ----它的索引项是:34。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 02 ----指向声明方法的类描述符CONSTANT_Class_info的索引项:2。

  00 23 ----指向名称及类型描述符CONSTANT_NameAndType的索引项:35。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 0E ----指向声明方法的类描述符CONSTANT_Class_info的索引项:14。

  00 24 ----指向名称及类型描述符CONSTANT_NameAndType的索引项:36。

09 --- 9,说明这是一个字段的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 25 ----指向声明字段类型的类或者接口描述符CONSTANT_Class_Info的索引:37,

  00 26 ---- 指向字段描述符CONSTANT_NameAndType的索引项:38,

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 02 ----指向声明方法的类描述符CONSTANT_Class_info的索引项:2。

  00 27 ----指向名称及类型描述符CONSTANT_NameAndType的索引项:39。

0A ----10,说明这是一个指向类中方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 28 ----指向声明方法的类描述符CONSTANT_Class_info的索引项:40。

  00 29 ----指向名称及类型描述符CONSTANT_NameAndType的索引项:41。

08 ----8,说明这是字符串类型字面量,根据它的表结构可知,接下的2个字节是它的内容。

  00 2A ----它的索引项是:42。

09 --- 9,说明这是一个字段的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 0E ----指向声明字段类型的类或者接口描述符CONSTANT_Class_Info的索引:14。

  00 2B ---- 指向字段描述符CONSTANT_NameAndType的索引项:43。

09 --- 9,说明这是一个字段的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 0E ----指向声明字段类型的类或者接口描述符CONSTANT_Class_Info的索引:14。

  00 2C ---- 指向字段描述符CONSTANT_NameAndType的索引项:44。

07 ----7,说明这是一个类或接口的符号引用。根据它的表结构可知,接下的2个字节是它的内容。

  00 2D ----指向全限定名常量的索引:45。

07 ----7,说明这是一个类或接口的符号引用。根据它的表结构可知,接下的2个字节是它的内容。

  00 2E ----指向全限定名常量的索引:46。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 03 ----UTF-8编码的字符串占用的字节数:3。

  54 41 47 ----字符串内容,根据ASCII编码表可得到字符串内容:TAG。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 12 ----UTF-8编码的字符串占用的字节数:18。

  4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B ----字符串内容,根据ASCII编码表得到字符串:Ljava/lang/String;

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 05 ----UTF-8编码的字符串占用的字节数:5。

  6D 54 79 70 65 ----字符串内容,根据ASCII编码表可得到字符串内容:mType。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 01 ----UTF-8编码的字符串占用的字节数:1。

  49 ----字符串内容,根据ASCII编码表可得到字符串内容:I。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 06 ----UTF-8编码的字符串占用的字节数:6。

  3C 69 6E 69 74 3E----字符串内容,根据ASCII编码表可得到字符串内容:<init>。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 03 ----UTF-8编码的字符串占用的字节数:3。

  28 29 56----字符串内容,根据ASCII编码表可得到字符串内容:()V。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 04 ----UTF-8编码的字符串占用的字节数:4。

  43 6F 64 65----字符串内容,根据ASCII编码表可得到字符串内容:Code。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 0F ----UTF-8编码的字符串占用的字节数:15。

  4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65----字符串内容,根据ASCII编码表可得到字符串内容:LineNumberTable。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 04 ----UTF-8编码的字符串占用的字节数:4。

  6D 61 69 6E ----字符串内容,根据ASCII编码表可得到字符串内容:main。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 16 ----UTF-8编码的字符串占用的字节数:22。

  28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 ----字符串内容,根据ASCII编码表可得到字符串内容:(Ljava/lang/String;)V。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 05 ----UTF-8编码的字符串占用的字节数:5。

  70 72 69 6E 74 ----字符串内容,根据ASCII编码表可得到字符串内容:print。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 11 ----UTF-8编码的字符串占用的字节数:17。

  28 4C 62 75 69 6C 64 2F 50 65 72 73 6F 6E 3B 29 56 ----字符串内容,根据ASCII编码表可得到字符串内容:(Lbuild/Person;)V。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 08 ----UTF-8编码的字符串占用的字节数:8。

  3C 63 6C 69 6E 69 74 3E ----字符串内容,根据ASCII编码表可得到字符串内容:<clinit>。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 0A ----UTF-8编码的字符串占用的字节数:10。

  53 6F 75 72 63 65 46 69 6C 65 ----字符串内容,根据ASCII编码表可得到字符串内容:SourceFile。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 09 ----UTF-8编码的字符串占用的字节数:9。

  4D 61 69 6E 2E 6A 61 76 61 ----字符串内容,根据ASCII编码表可得到字符串内容:Main.java。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 14 ----指向该字段或方法名称常量项的索引:20。

  00 15 ----指向该字段或方法描述符常量项的索引:21。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 0C ----UTF-8编码的字符串占用的字节数:12。

  62 75 69 6C 64 2F 50 65 72 73 6F 6E ----字符串内容,根据ASCII编码表可得到字符串内容:build/Person。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 2F ----指向该字段或方法名称常量项的索引:47。

  00 30 ----指向该字段或方法描述符常量项的索引:48。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 09 ----UTF-8编码的字符串占用的字节数:9。

  E8 8C 83 E5 86 B0 E5 86 B0 ----字符串内容,根据ASCII编码表可得到字符串内容:范冰冰。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 31  ----指向该字段或方法名称常量项的索引:49。

  00 32 ----指向该字段或方法描述符常量项的索引:50。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 1A  ----指向该字段或方法名称常量项的索引:26。

  00 1B ----指向该字段或方法描述符常量项的索引:27。

07 ----7,说明这是一个类或接口的符号引用。根据它的表结构可知,接下的2个字节是它的内容。

  00 33 ----指向全限定名常量的索引:51。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 34  ----指向该字段或方法名称常量项的索引:52。

  00 35 ----指向该字段或方法描述符常量项的索引:53。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 36  ----指向该字段或方法名称常量项的索引:54。

  00 37 ----指向该字段或方法描述符常量项的索引:55。

07 ----7,说明这是一个类或接口的符号引用。根据它的表结构可知,接下的2个字节是它的内容。

  00 38 ----指向全限定名常量的索引:56。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 39  ----指向该字段或方法名称常量项的索引:57。

  00 32 ----指向该字段或方法描述符常量项的索引:50。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 0D ----UTF-8编码的字符串占用的字节数:13。

  54 68 69 73 20 69 73 20 61 20 74 61 67 ----字符串内容,根据ASCII编码表可得到字符串内容:This is a tag。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 10  ----指向该字段或方法名称常量项的索引:16。

  00 11 ----指向该字段或方法描述符常量项的索引:17。

0C ----12,说明这是一个字段或方法的符号引用,根据它的表结构可知,接下的4个字节是它的内容。

  00 12  ----指向该字段或方法名称常量项的索引:18。

  00 13 ----指向该字段或方法描述符常量项的索引:19。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 0A ----UTF-8编码的字符串占用的字节数:10。

  62 75 69 6C 64  2F 4D 61 69 6E ----字符串内容,根据ASCII编码表可得到字符串内容:Build/Main。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 10 ----UTF-8编码的字符串占用的字节数:16。

 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74----字符串内容,根据ASCII编码表可得到字符串内容:java/lang/Object。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 06 ----UTF-8编码的字符串占用的字节数:6。

 73 65 74 41 67 65----字符串内容,根据ASCII编码表可得到字符串内容:setAge。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 04 ----UTF-8编码的字符串占用的字节数:4。

 28 49 29 56----字符串内容,根据ASCII编码表可得到字符串内容:(I)V。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 07 ----UTF-8编码的字符串占用的字节数:7。

 73 65 74 4E 61 6D 65----字符串内容,根据ASCII编码表可得到字符串内容:setName。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 15 ----UTF-8编码的字符串占用的字节数:21。

 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 ----字符串内容,根据ASCII编码表可得到字符串内容:(Ljava/lang/String;)V。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 10 ----UTF-8编码的字符串占用的字节数:16。

 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D ----字符串内容,根据ASCII编码表可得到字符串内容:java/lang/System。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 03 ----UTF-8编码的字符串占用的字节数:3。

 6F 75 74 ----字符串内容,根据ASCII编码表可得到字符串内容:out。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 15 ----UTF-8编码的字符串占用的字节数:21。

 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B ----字符串内容,根据ASCII编码表可得到字符串内容:Ljava/io/PrintSystem;。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 08 ----UTF-8编码的字符串占用的字节数:8。

 74 6F 53 74 72 69 6E 67 ----字符串内容,根据ASCII编码表可得到字符串内容:toString。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 14 ----UTF-8编码的字符串占用的字节数:20。

 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B  ----字符串内容,根据ASCII编码表可得到字符串内容:()Ljava/lang/String;。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 13 ----UTF-8编码的字符串占用的字节数:19。

 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72  ----字符串内容,根据ASCII编码表可得到字符串内容:java/io/PrintStream。

01 ----1,说明这是一个UTF-8编码的字符串,根据它的表结构可知,接下的2个字节是它的长度。

  00 07----UTF-8编码的字符串占用的字节数:7。

 70 72 69 6E 74 6C 6E  ----字符串内容,根据ASCII编码表可得到字符串内容:println。

00 21----访问标志,标识这是一个普通的Java类,不是接口、枚举或注解,被public关键字修饰但没有被声明为final和abstrace。

00 0E ----类索引,表明这个类的全限定名,索引值为14。

00 0F ----父类索引,表明这个类的父类的全限定名,索引值为15。

00 00 ---- 接口计数器,说明这个类中没有接口,也就没有接口索引集合。

00 02 ----字段个数:2

待续。。。

猜你喜欢

转载自blog.csdn.net/u010838555/article/details/102768273