Java字节码
类型 | 名称 | 数量 |
---|---|---|
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count - 1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interfaces_count | 1 |
u2 | interfaces | interfaces_count |
u2 | fields_count | 1 |
field_info | fields | fields_count |
u2 | methods_count | 1 |
method_info | methods | methods_count |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: CA FE BA BE 00 00 00 34 00 16 0A 00 04 00 12 09 J~:>...4........
00000010: 00 03 00 13 07 00 14 07 00 15 01 00 01 6D 01 00 .............m..
00000020: 01 49 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 .I...<init>...()
00000030: 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E V...Code...LineN
00000040: 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F 63 umberTable...Loc
00000050: 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 alVariableTable.
00000060: 00 04 74 68 69 73 01 00 1C 4C 63 6F 6D 2F 7A 63 ..this...Lcom/zc
00000070: 2F 73 72 6A 76 6D 2F 63 30 36 2F 54 65 73 74 43 /srjvm/c06/TestC
00000080: 6C 61 73 73 3B 01 00 03 69 6E 63 01 00 03 28 29 lass;...inc...()
00000090: 49 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 I...SourceFile..
000000a0: 0E 54 65 73 74 43 6C 61 73 73 2E 6A 61 76 61 0C .TestClass.java.
000000b0: 00 07 00 08 0C 00 05 00 06 01 00 1A 63 6F 6D 2F ............com/
000000c0: 7A 63 2F 73 72 6A 76 6D 2F 63 30 36 2F 54 65 73 zc/srjvm/c06/Tes
000000d0: 74 43 6C 61 73 73 01 00 10 6A 61 76 61 2F 6C 61 tClass...java/la
000000e0: 6E 67 2F 4F 62 6A 65 63 74 00 21 00 03 00 04 00 ng/Object.!.....
000000f0: 00 00 01 00 02 00 05 00 06 00 00 00 02 00 01 00 ................
00000100: 07 00 08 00 01 00 09 00 00 00 2F 00 01 00 01 00 ........../.....
00000110: 00 00 05 2A B7 00 01 B1 00 00 00 02 00 0A 00 00 ...*7..1........
00000120: 00 06 00 01 00 00 00 09 00 0B 00 00 00 0C 00 01 ................
00000130: 00 00 00 05 00 0C 00 0D 00 00 00 01 00 0E 00 0F ................
00000140: 00 01 00 09 00 00 00 31 00 02 00 01 00 00 00 07 .......1........
00000150: 2A B4 00 02 04 60 AC 00 00 00 02 00 0A 00 00 00 *4...`,.........
00000160: 06 00 01 00 00 00 0E 00 0B 00 00 00 0C 00 01 00 ................
00000170: 00 00 07 00 0C 00 0D 00 00 00 01 00 10 00 00 00 ................
00000180: 02 00 11 ...
魔数
开头4个字节的十六进制表示是0xCAFEBABE
次版本和主版本
代表次版本号的第5个和第6个字节值为0x0000,而主版本号的值为0x0032,也即是十进制的50,该版本号说明这个是可以被JDK 6或以上版本虚拟机执行的Class文件。
0x0034,十进制52.JDK8
常量池
紧接着主、次版本号之后的是常量池入口,常量池可以比喻为Class文件里的资源仓库,它是Class文件结构中与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一,另外,它还是在Class文件中第一个出现的表类型数据项目。
由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值( constant_pool_count )。
与Java中语言习惯不同,这个容量计数是从1而不是0开始的
constant_pool_count
0x0016,即十进制的22
,这就代表常量池中有21项常量
,索引值范围为1~21。
01
CONSTANT_Methodref_info 结构的各项说明:
◆ class_index 指向的常量必须是一个 CONSTANT_Class_Info 常量,表示当前方法所在的类的类名;
◆ name_and_type_index 指向的常量必须是一个 CONSTANT_NameAndType_info 常量,表示当前 方法的名字 和 方法描述符。
02
CONSTANT_Fieldref_info 存储 字段的符号信息
◆ class_index 指向的常量必须是一个 CONSTANT_Class_Info 常量,表示当前字段所在的类的类名;此处是#3 TestClass
◆ name_and_type_index 指向的常量必须是一个 CONSTANT_NameAndType_info 常量,表示当前字段的名字和类型描述符。 此处是 #19 int m
03
CONSTANT_Class_Info 常量存储类的符号信息,除 tag 字段外,
只有一个存储 指向常量池表中某一常量的索引字段 name_index,
name_index 指向的常量 必须是一个 CONSTANT_Utf8_info 常量,该常量存储 class 的类名. 此处为 #20 TestClass
类信息.
04
同上. Object类 的类型信息.指向 #21
05~09
CONSTANT_Utf8_info 常量结构用于存储字符串常量,字符串编码使用 UTF-8。
除一个必须的 tag 字段和存储字符串的字节数组外, 还要有一个字段存储描述这个字符串字节数组的长度
10
11
12
13-17
javap
➜ myshell javap -verbose /Users/duandian/Documents/0zc/02-my/00-code/02-gitee/MyCommons/jvm/target/classes/com/zc/srjvm/c06/TestClass.class
Classfile /Users/duandian/Documents/0zc/02-my/00-code/02-gitee/MyCommons/jvm/target/classes/com/zc/srjvm/c06/TestClass.class
Last modified 2021-4-20; size 387 bytes
MD5 checksum 58d9d83b4f3952f4f405ab65ad35a34d
Compiled from "TestClass.java"
public class com.zc.srjvm.c06.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#18 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#19 // com/zc/srjvm/c06/TestClass.m:I
#3 = Class #20 // com/zc/srjvm/c06/TestClass
#4 = Class #21 // java/lang/Object
#5 = Utf8 m
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/zc/srjvm/c06/TestClass;
#14 = Utf8 inc
#15 = Utf8 ()I
#16 = Utf8 SourceFile
#17 = Utf8 TestClass.java
#18 = NameAndType #7:#8 // "<init>":()V
#19 = NameAndType #5:#6 // m:I
#20 = Utf8 com/zc/srjvm/c06/TestClass
#21 = Utf8 java/lang/Object
{
public com.zc.srjvm.c06.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/zc/srjvm/c06/TestClass;
public int inc();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field m:I
4: iconst_1
5: iadd
6: ireturn
LineNumberTable:
line 14: 0
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lcom/zc/srjvm/c06/TestClass;
}
SourceFile: "TestClass.java"
第一个常量池 0A,即10,类中方法的符号引用
18
CONSTANT_NameAndType_info 结构用于 存储 字段的名称 和 字段的类型描述符, 或者是用于存储 方法的名称 和 方法的描述符。
CONSTANT_NameAndType_info 结构除 tag 字段外, 还有一个 U2 类型的字段 name_index 和一个 U2 类型的字段 descriptor_index, 分别对应 名称指向常量池中某个常量的索引 和 描述符指向常量池中某个常量的索引,这两个字段指向的常量都必须是 CONSTANT_Utf8_info 结构的常量。
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}