欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

0.从0开始的手写java虚拟机-class文件示例解读

程序员文章站 2022-03-26 15:46:58
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//public class ClassFileTest { public static final boolean FLAG = false; public static final byte BYTE = 123; public static final char X = '...

前言:
笔者最近在阅读《手写 Java 虚拟机》,在实践过程中也遇到了诸多疑问,所谓书山有路勤为径,因而希望能够将我的阅读心得记录下来,供同好互相交流;
以下是一个非常简单明了的 class 文件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public class ClassFileTest {
    public static final boolean FLAG = false;
    public static final byte BYTE = 123;
    public static final char X = 'X';
    public static final short SHORT = 12345;
    public static final int INT = 123456789;
    public static final long LONG = 1234567L;
    public static final float PI = 3.1415925F;
    public static final double E = 2.71828D;

    public ClassFileTest() {
    }

    public static void main(String[] args) {
        System.out.println("HelloWorld");
    }
}

其 16 进制文件对应为

CA FE BA BE 00 00 00 3A 00 3D 0A 00 02 00 03 07 00 04 0C 00 05 00 06 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 09 00 08 00 09 07 00 0A 0C 00 0B 00 0C 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 08 00 0E 01 00 0A 48 65 6C 6C 6F 57 6F 72 6C 64 0A 00 10 00 11 07 00 12 0C 00 13 00 14 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 07 00 16 01 00 0D 43 6C 61 73 73 46 69 6C 65 54 65 73 74 01 00 04 46 4C 41 47 01 00 01 5A 01 00 0D 43 6F 6E 73 74 61 6E 74 56 61 6C 75 65 03 00 00 00 00 01 00 04 42 59 54 45 01 00 01 42 03 00 00 00 7B 01 00 01 58 01 00 01 43 03 00 00 00 58 01 00 05 53 48 4F 52 54 01 00 01 53 03 00 00 30 39 01 00 03 49 4E 54 01 00 01 49 03 07 5B CD 15 01 00 04 4C 4F 4E 47 01 00 01 4A 05 00 00 00 00 00 12 D6 87 01 00 02 50 49 01 00 01 46 04 40 49 0F DA 01 00 01 45 01 00 01 44 06 40 05 BF 09 95 AA F7 90 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 0F 4C 43 6C 61 73 73 46 69 6C 65 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 12 43 6C 61 73 73 46 69 6C 65 54 65 73 74 2E 6A 61 76 61 00 21 00 15 00 02 00 00 00 08 00 19 00 17 00 18 00 01 00 19 00 00 00 02 00 1A 00 19 00 1B 00 1C 00 01 00 19 00 00 00 02 00 1D 00 19 00 1E 00 1F 00 01 00 19 00 00 00 02 00 20 00 19 00 21 00 22 00 01 00 19 00 00 00 02 00 23 00 19 00 24 00 25 00 01 00 19 00 00 00 02 00 26 00 19 00 27 00 28 00 01 00 19 00 00 00 02 00 29 00 19 00 2B 00 2C 00 01 00 19 00 00 00 02 00 2D 00 19 00 2E 00 2F 00 01 00 19 00 00 00 02 00 30 00 02 00 01 00 05 00 06 00 01 00 32 00 00 00 2F 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 02 00 33 00 00 00 06 00 01 00 00 00 01 00 34 00 00 00 0C 00 01 00 00 00 05 00 35 00 36 00 00 00 09 00 37 00 38 00 01 00 32 00 00 00 37 00 02 00 01 00 00 00 09 B2 00 07 12 0D B6 00 0F B1 00 00 00 02 00 33 00 00 00 0A 00 02 00 00 00 0D 00 08 00 0E 00 34 00 00 00 0C 00 01 00 00 00 09 00 39 00 3A 00 00 00 01 00 3B 00 00 00 02 00 3C

首先,通过查阅JVM 官方文档第 4 章,笔者了解到了 class 文件的基本格式

ClassFile {
    (1)u4       magic;
    (2)u2       minor_version;
    (3)u2       major_version;
    (4)u2       constant_pool_count;
    (5)cp_info  constant_pool[constant_pool_count-1];
    (6)u2       access_flags;
    (7)u2       this_class;
    (8)u2       super_class;
    (9)u2       interfaces_count;
    (10)u2      interfaces[interfaces_count];
    (11)u2       fields_count;
    (12)field_info     fields[fields_count];
    (13)u2             methods_count;
    (14)method_info    methods[methods_count];
    (15)u2             attributes_count;
    (16)attribute_info attributes[attributes_count];
}

为避免叙述的混乱,因此我在每一个字段前加上了一个序号

u4 => 无符号 4 字节|
u2 => 无符号 2 字节
其他以此类推;

CA FE BA BE ((1)magic)

00 00 ((2)minor_version:0)

00 3A ((3)major_version:0x3A(58))

00 3D ((4)constant_pool_count: 61)


(5)cp_info[constant_pool_count]

(ps:字符串常量池的大小等于constant_pool中实际大小+1,且id从1开始,且long和double占2格)

cp_info{u1 tag; u1 info[]}

此处info详情如下:
cp_info常量池分类如下表:

tag name struct
1 CONSTANT_Utf8 {u1 tag; u2 length; u1 bytes[length]}
3 CONSTANT_Integer {u1 tag; u4 bytes;}
4 CONSTANT_Float {u1 tag; u4 bytes;}
5 CONSTANT_Long {u1 tag; u4 high_bytes; u4 low_bytes;}
6 CONSTANT_Double {u1 tag; u4 high_bytes; u4 low_bytes;}
7 CONSTANT_Class {u1 tag; u2 name_index;}
8 CONSTANT_String {u1 tag; u2 string_index;}
9 CONSTANT_Fieldref {u1 tag; u2 class_Index; u2 name_and_type_index;}
10 CONSTANT_Methodref {u1 tag; u2 class_index; u2 name_and_type_index;}
11 CONSTANT_InterfaceMethodref {u1 tag; u2 class_index; u2 name_and_type_index;}
12 CONSTANT_NameAndType {u1 tag; u2 name_index; u2 descriptor_index;}
15 CONSTANT_MethodHandle {u1 tag; u2 reference_kind; u2 reference_index;}
16 CONSTANT_MethodType {u1 tag; u2 descriptor_index;}
17 CONSTANT_Dynamic {u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index;}
18 CONSTANT_invokedynamic {u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index;}
19 CONSTANT_Module {u1 tag; u2 name_index;}
20 CONSTANT_Package {u1 tag; u2 name_index;}

(1)(tag:10) 0A
(class_index:02) 00 02
(name_and_type_index:03) 00 03

(2)(tag:07) 07
(name_index:04) 00 04

(3)(tag:12) 0C
(name_index:05) 00 05
(descriptor_index:06;) 00 06

(4)(tag:01) 01
(length:16) 00 10
(bytes[length]:java/lang/Object) 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74

(5)(tag:01) 01
(length:06) 00 06
(bytes[length]:) 3C 69 6E 69 74 3E

//以下省略tag名称

(6) 01
(length:03) 00 03
(bytes[length]:()V) 28 29 56

(7)09
(class_index:08) 00 08
(name_and_type_index:09) 00 09

(8)07
(class_index:10) 00 0A

(9)0C
(name_index:11) 00 0B
(descriptor_index:12) 00 0C

(10)01
(length:10) 00 10
(bytes[length]:java/lang/System) 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D

(11)01
(length:03) 00 03
(bytes[length]:out) 6F 75 74

(12)01
(length:21) 00 15
(bytes[length]:Ljava/io/PrintStream;) 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B

(13)08
(string_index:14) 00 0E

(14)01
(length:10) 00 0A
(bytes[length]:HelloWorld) 48 65 6C 6C 6F 57 6F 72 6C 64

(15)0A
(class_index:16) 00 10
(name_and_type_index:17) 00 11

(16)07
(name_index:18) 00 12

(17)0C
(name_index:19) 00 13
(descriptor_index:20) 00 14

(18)01
(legth:19) 00 13
(bytes[length]:java/io/PrintStream) 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D

(19)01
(length:07) 00 07
(bytes[length]:println) 70 72 69 6E 74 6C 6E

(20)01
(length:21) 00 15
(bytes[length]:(Ljava/lang/String;)V) 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56

(21)07
(name_index:22) 00 16

(22)01
(length:13) 00 0D
(bytes[length]:ClassFileTest) 43 6C 61 73 73 46 69 6C 65 54 65 73 74

(23)01
(length:04) 00 04
(bytes[length]:FLAG) 46 4C 41 47

(24)01
(length:01) 00 01
(bytes[length:Z]) 5A

(25)01
(length:13) 00 0D
(bytes[length]:ConstantValue) 43 6F 6E 73 74 61 6E 74 56 61 6C 75 65

(26)03
(Integer:0) 00 00 00 00

(27)01
(length:04) 00 04
(bytes[length]:BYTE) 42 59 54 45

(28)01
(length:01) 00 01
(bytes[length]:B) 42

(29)03
(Integer:123) 00 00 00 7B

(30)01
(length:01) 00 01
(bytes[length]:X) 58

(31)01
(length:01) 00 01
(bytes[length]:C) 43

(32)03
(Integer:88) 00 00 00 58

(33)01
(length:05) 00 05
(bytes[length]:SHORT) 53 48 4F 52 54

(34)01
(length:01) 00 01
(bytes[length]:S) 53

(35)03
(Integer:12345) 00 00 30 39

(36)01
(length:03) 00 03
(bytes[length]:INT) 49 4E 54

(37)01
(length:01) 00 01
**(bytes[length]:I)49

(38)03
(Integer:123456789) 07 5B CD 15

(39)01
(length:04) 00 04
(bytes[length]:LONG) 4C 4F 4E 47

(40)01
(length:01) 00 01
(bytes[length]:J) 4A

(41)05
(Long:1234567)
(high_bytes:0x00000000) 00 00 00 00
(low_bytes) 00 12 D6 87

(ps:Long和double占2个位置)

(43)01
(length:02) 00 02
(bytes[length]:PI) 50 49

(44)01
(length:01) 00 01
(bytes[length]:F) 46

(45)04
(Float(IEEE754):3.1415925) 40 49 0F DA

(46)01
(length:01) 00 01
(bytes[length]:E) 45

(47)01
(length:01)) 00 01
(bytes[length]????) 44

(48)06
(Double:2.71828)
(high_bytes) 40 05 BF 09
(low_bytes) 95 AA F7 90

(50)01
(length:04) 00 04
(bytes[length]:Code) 43 6F 64 65

(51)01
(length:15) 00 0F
(bytes[length]:LineNumberTable) 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65

(52)01
(length:18) 00 12
(bytes[length]:LocalVariableTable) 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65

(53)01
(length:04) 00 04
(bytes[length]:this) 74 68 69 73

(54)01
(length:15) 00 0F
(bytes[length]:LClassFileTest;) 4C 43 6C 61 73 73 46 69 6C 65 54 65 73 74 3B

(55)01
(length:04) 00 04
(bytes[length]:main) 6D 61 69 6E

(56)01
(length:22) 00 16
(bytes[length]:([Ljava/lang/String;)V) 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56

(57)01
(length:4) 00 04
(bytes[length]:args) 61 72 67 73

(58)01
(length:19) 00 13
(bytes[length][Ljava/lang/String;) 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B

(59)01
(length:10) 00 0A
(bytes[length]:SourceFile) 53 6F 75 72 63 65 46 69 6C 65

(60)01
(length:12) 00 12
(bytes[length]:ClassFIleTest.java) 43 6C 61 73 73 46 69 6C 65 54 65 73 74 2E 6A 61 76 61


自此,class文件常量池已分析完毕。

(6)access_flag

flag name value
ACC_PUBLIC 0x0001
ACC_PRIVATE 0x0002
ACC_PROTECTED 0x0004
ACC_STATIC 0x0008
ACC_FINAL 0x0010
ACC_VOLATILE 0x0040
ACC_TRANSIENT 0x0080
ACC_SYNTHETIC 0x1000
ACC_ENUM 0x4000
ACC_SUPER 0x0020
ACC_INTERFACE 0x0200
ACC_ABSTRACT 0x0400
ACC_ANNOTATION 0x2000
ACC_MODULE 0x8000

(0x0001(ACC_PUBLIC) + 0x0020(ACC_SUPER)) 00 21

(7)(常量池索引)this_class(=>21)ClassFileTest 00 15

(8)(常量池索引)super_class(=>02)java/lang/Object 00 02

(9)interface_count:0 00 00

(10)interfaces[interface_count]


//以下开始字段的描述

(11)fields_count 00 08 (一共8个字段)

(12)fields[fields_count]

field_info{
  u2 access_flags;
  u2 name_index;
  u2 descriptor_index;
  u2 attributes_count;
  attribute_info attributes[attributes_count];
}

attribute_info{
  u2 attribute_name_index;
  u4 attribute_length;
  u1 info[attribute_length];
}

//对于descriptor(描述符)

fieldTypeItem Type
B byte
C char
D double
F float
I int
J long
L<Classname>; reference
S short
Z boolean
[ one array dimension reference

以下涉及到attribute;

ConstantValue_attribute{
  u2 attribute_name_index;
  u4 attribute_length;
  u2 constantvalue_index;
}

一共8个字段

(1)

(access_flags:0x0001(ACC_PUBLIC)+0x0010(ACC_Final)+0x0008(ACC_STATIC)) 00 19

(name_index:23=>FLAG) 00 17

(descriptor_index:24=>Z) 00 18

(attribute_count:1) 00 01

(attribute_name_index:25=>ConstantValue) 00 19

Constantvalue_attribute->

(attribute_length:02) 00 00 00 02

(constanvalue_index:2->0) 00 1A

(2)

(access_flags:public static final) 00 19

(name_index:27->BYTE) 00 1B

(descriptor_index:28->B) 00 1C

(attributes_count:1) 00 01

(attribute_name_index:25->ConstantValue) 00 19

Constantvalue_attribute->

(attribute_length:02) 00 00 00 02

(constantvalue_index:29->123) 00 1D

(3)

(access_flags:public static final) 00 19

(name_index:30->X) 00 1E

(descriptor_index:31->C) 00 1F

(attributes_count:01) 00 01

(attribute_name_index:25->ConstantValue) 00 19

Constantvalue_attribute->

(attribute_length:02) 00 00 00 02

(constantvalue_index:32->88(‘C’)) 00 20

(4)

(access_flags:public static final) 00 19

(name_index:33->SHORT) 00 21

(descriptor_index:34) 00 22

(attributes_count:01) 00 01

(attribute_name_index:25->ConstantValue) 00 19

Constantvalue_attribute->

(attribute_length:02) 00 00 00 02

(constantvalue_index:35->12345) 00 23

(5)

(access_flags:public static final) 00 19

(name_index:36->INT) 00 24


(descriptor_index:37->I) 00 25

(attributes_count:01) 00 01

ConstantValue_attribute->

(attribute_name_index:25->ConstantValue) 00 19

(attribute_length:02) 00 00 00 02

(constantvalue_index:38->123456789;) 00 26

(6)

(access_flags:public static final) 00 19

(name_index:39->LONG) 00 27

(descriptor_index:40->J) 00 28

(attributes_count:01) 00 01

(attribute_name_index:25->ConstantValue) 00 19

ConstantValueAttribute->

(attribute_length:02) 00 00 00 02

(constantvalue_index:41->1234567) 00 29

(7)

(access_flags:public static final) 00 19

(name_index:43->PI) 00 2B

(descriptor_index:44->F) 00 2C

(attributes_count:01) 00 01

(attribute_name_index:25->ConstantValue) 00 19

ConstantValue_attribute->

(attribute_length:02) 00 00 00 02

(constantValue_index:45->3.1415925) 00 2D

(8)

(access_flags:public static final) 00 19

(name_index:46->E) 00 2E

(descriptor_index:47->D) 00 2F

(attributes_count:01) 00 01

(attribute_name_index:25->ConstantValue) 00 19

ConstantValue_attribute->

(attribute_length:02) 00 00 00 02

(constantvalue_index:48->2.71828;) 00 30


以下要开始方法的描述了

method_info{
  u2 access_flags;
  u2 name_index;
  u2 descriptor_index;
  attribute_info attributes[attributes_count];
}
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];
}

(12)methods_count: 00 02

(13)methods[methods_count]

(1)

(access_flags:public) 00 01

(name_index:05->) 00 05

(descriptor_index:06->()V) 00 06

(attributes_count:01) 00 01

(attribute_name_index:50->Code) 00 32

(attribute_length:47) 00 00 00 2F

(max_stacks:01) 00 01

(max_lcoals:01) 00 01

(code_length:05) 00 00 00 05

以下设计到jvm指令集具体请查阅官网此处仅给出部分:

id value format
0x2A aload_0
0xB7 invokespecial
0xB1 return invokespecial indexbyte1 indexbyte2

(code:)

2A

B7 00 01

B1

  aload_0
  invokespecial 01
  return

(exception_table_length:0) 00 00

(attributes_count:02) 00 02

(attribute_name_index:51->LineNumberTable) 00 33

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];  
}

(attribute_length:06) 00 00 00 06

(line_number_table_length:01) 00 01

(start_pc:0) 00 00

(end_pc:01) 00 01

(attribue_name_index:52->LocalVariableTable) 00 34

(attribute_length:12) 00 00 00 0C

(local_variable_table_length:01) 00 01

(start_pc:0;) 00 00

(length:05) 00 05

(name_index:53->this) 00 35

(descriptor_index:54->LClassFileTest;) 00 36

(index:0;) 00 00

(2)

(access_flags:public static) 00 09

(name_index:55->main) 00 37

(descriptor_index:56->(Ljava/lang/String;)V) 00 38

(attributes_count:01) 00 01

(attribute_name_index:50->Code) 00 32

(attribute_length:55;) 00 00 00 37

(max_stacks:02) 00 02

(max_locals:01) 00 01

(code_length:09) 00 00 00 09

id value format
0xB2 getstatic getstatic indexbyte1 indexbyte2
0x12 ldc ldc index
0xB6 invokevirtual invokevirtual indexbyte1 indexbyte2
0xB1 return

B2 00 07

12 0D

B6 00 0F

B1

  getstatic 07
  ldc 13
  invokevirtual 15
  return

(exception_table_length:0) 00 00

(attributes_count:02;) 00 02

(attribute_name_index:51->LineNumberTable) 00 33

(attribute_length:10) 00 00 00 0A

(line_number_table_length:02) 00 02

(start_pc:0) 00 00

(line_number:13) 00 0D

(start_pc:8) 00 08

(end_pc:14) 00 0E

(attribute_name_index:52->LocalVariableTable) 00 34

(attribute_length:12) 00 00 00 0C

(local_variable_table_length:01) 00 01

(start_pc:0) 00 00

(length:09) 00 09

(name_index:57->args) 00 39

(descriptor_index:58->Ljava/lang/String;) 00 3A

(index:0) 00 00


14.attributes_count: 00 01

(attribute_name_index:59->SourceFile) 00 3B

SourceFile_attribute{
  u2 attribute_name_index;
  u4 attribute_length;
  u2 sourcefile_index;
}

(attribute_length:02) 00 00 00 02

(sourcefile_index:60->ClassFileTest.java) 00 3C

本文地址:https://blog.csdn.net/Yuan_xii/article/details/113915929

相关标签: jvm java