本文通過解析Class文件中字節(jié)碼的結(jié)構(gòu)牙瓢,來加深對(duì)Java類文件結(jié)構(gòu)的理解毡代。建議先閱讀Java類文件結(jié)構(gòu)解析這篇文章阅羹。
Test.java
package org.tianbin.clazz;
public class Test{
private int m;
public int inc(){
return m + 1;
}
}
Test.class
CA FE BA BE 00 00 00 34 00 13 0A 00 04 00 0F 09 00 03 00 10 07 00
11 07 00 12 01 00 01 6D 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 03 69 6E 63 01 00 03 28 29 49 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 07 00 08 0C 00 05 00 06 01 00 16 6F 72 67 2F 74 69 61 6E
62 69 6E 2F 63 6C 61 7A 7A 2F 54 65 73 74 01 00 10 6A 61 76 61 2F
6C 61 6E 67 2F 4F 62 6A 65 63 74 00 21 00 03 00 04 00 00 00 01 00
02 00 05 00 06 00 00 00 02 00 01 00 07 00 08 00 01 00 09 00 00 00
1D 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 01 00 0A 00 00
00 06 00 01 00 00 00 03 00 01 00 0B 00 0C 00 01 00 09 00 00 00 1F
00 02 00 01 00 00 00 07 2A B4 00 02 04 60 AC 00 00 00 01 00 0A 00
00 00 06 00 01 00 00 00 07 00 01 00 0D 00 00 00 02 00 0E
魔數(shù)
CA FE BA BE
class文件的頭4個(gè)字節(jié),用于驗(yàn)證該文件是否能夠被虛擬機(jī)接受
主次版本號(hào)
00 00 00 34
魔數(shù)后4個(gè)字節(jié)教寂,第5個(gè)和第6個(gè)字節(jié)是次版本號(hào)(Minor Version)捏鱼,第7個(gè)和第8個(gè)字節(jié)是主版本號(hào)(Major Version),Test.java文件使用JDK1.8進(jìn)行編譯,所以主版本號(hào)為00 34
酪耕,十進(jìn)制表示為52导梆。
常量池
結(jié)構(gòu):容量計(jì)數(shù)器(u2類型) + 常量
00 13
容量計(jì)算器,計(jì)數(shù)從1開始迂烁,目的是滿足某些常量池的索引值的數(shù)據(jù)在特定情況下需要表達(dá)“不引用任何一個(gè)常量池”的含義看尼。當(dāng)前容量計(jì)算器值為19,表示常量池中有18項(xiàng)常量婚被,索引值范圍為1~18。
常量1
0A
00 04 //java/lang/Object
00 0F //<init>
字節(jié)碼 | 結(jié)構(gòu) | 含義 |
---|---|---|
0A | tag | 值為10梳虽,CONSTANT_Methodref_info |
00 04 | index | 指向聲明方法的類描述符CONSTANT_Class_info的索 |
00 0F | index | 指向名稱及類型描述符CONSTANT_NameAndType的索引項(xiàng) |
常量2
09
00 03 //org/tianbin/clazz/Test
00 10 //m
字節(jié)碼 | 結(jié)構(gòu) | 含義 |
---|---|---|
09 | tag | 值為9址芯,CONSTANT_Fieldref_info |
00 03 | index | 指向聲明字段的類或者接口描述符CONSTANT_Class_info的索引項(xiàng) |
00 10 | index | 指向字段描述符CONSTANT_NameAndType的索引項(xiàng) |
常量3
07
00 11 //常量17 org/tianbin/clazz/Test
字節(jié)碼 | 結(jié)構(gòu) | 含義 |
---|---|---|
07 | tag | 值為7,CONSTANT_Class_info |
00 11 | index | 指向全限定名常量項(xiàng)的索引 |
常量4
07
00 12 //常量18 java/lang/Object
結(jié)構(gòu)見常量3
常量5
01
00 01
6D //m
字節(jié)碼 | 結(jié)構(gòu) | 含義 |
---|---|---|
01 | tag | 值為1窜觉,CONSTANT_Utf8_info |
00 01 | length | UTF-8編碼字符串占用的字節(jié)數(shù) |
6D | bytes | 長(zhǎng)度為length的UTF-8編碼的字符串 |
常量6
01
00 01
49 //I
結(jié)構(gòu)見常量5
常量7
01
00 06
3C 69 6E 69 74 3E //<init>
結(jié)構(gòu)見常量5
常量8
01
00 03
28 29 56 //()V
結(jié)構(gòu)見常量5
常量9
01
00 04
43 6F 64 65 //Code
結(jié)構(gòu)見常量5
常量10
01
00 0F
4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 //LineNumberTable
結(jié)構(gòu)見常量5
常量11
01
00 03
69 6E 63 //inc
結(jié)構(gòu)見常量5
常量12
01
00 03
28 29 49 //()I
結(jié)構(gòu)見常量5
常量13
01
00 0A
53 6F 75 72 63 65 46 69 6C 65 //SourceFile
結(jié)構(gòu)見常量5
常量14
01
00 09
54 65 73 74 2E 6A 61 76 61 //Test.java
結(jié)構(gòu)見常量5
常量15
0C
00 07
00 08
字節(jié)碼 | 結(jié)構(gòu) | 含義 |
---|---|---|
0C | tag | 值為12谷炸,CONSTANT_NameAndType_info |
00 07 | index | 指向該字段或方法名稱常量的索引 |
00 08 | index | 指向該字段或方法描述符常量項(xiàng)的索引 |
常量16
0C
00 05
00 06
結(jié)構(gòu)見常量15
常量17
01
00 16
6F 72 67 2F 74 69 61 6E 62 69 6E 2F 63 6C 61 7A 7A 2F 54 65 73 74 //org/tianbin/clazz/Test
結(jié)構(gòu)見常量5
常量18
01
00 10
6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 //java/lang/Object
結(jié)構(gòu)見常量5
訪問標(biāo)志
00 21
常量池之后兩個(gè)字節(jié)標(biāo)識(shí)類的訪問標(biāo)志,用于識(shí)別一些類或者接口層次的訪問信息禀挫。
類索引旬陡、父類索引、接口索引
00 03 類索引 //org/tianbin/clazz/Test
00 04 父類索引 //java/lang/Object
00 00 接口索引集合大小
字段表集合
00 01 fields_count
00 02 access_flags
00 05 name_index //m
00 06 descriptor_index
00 00 attributes_count
方法表集合
00 02 method_count //<init> inc
init
字節(jié)碼 | 結(jié)構(gòu)名稱 | 含義 |
---|---|---|
00 01 | access_flag | |
00 07 | name_index | <init> |
00 08 | descriptor_index | |
00 01 | attributes_count | |
00 09 | attributes_name_index | Code |
00 00 00 1D | attribute_length | |
00 01 | max_stack | |
00 01 | max_local | |
00 00 00 05 | code_length | |
2A B7 00 01 B1 | code | |
00 00 | exception_table_length | |
00 01 | attributes_count | |
00 0A | attributes_name_index | LineNumberTable |
00 00 00 06 | attribute_length | |
00 01 | line_number_table_length | |
00 00 | start_pc | |
00 03 | line_number |
inc
字節(jié)碼 | 結(jié)構(gòu)名稱 | 含義 |
---|---|---|
00 01 | access_flag | |
00 0B | name_index | inc |
00 0C | descriptor_index | |
00 01 | attributes_count | |
00 09 | attributes_name_index | Code |
00 00 00 1F | attribute_length | |
00 02 | max_stack | |
00 01 | max_local | |
00 00 00 07 | code_length | |
2A B4 00 02 04 60 AC | code | |
00 00 | exception_table_length | |
00 01 | attributes_count | |
00 0A | attributes_name_index | LineNumberTable |
00 00 00 06 | attribute_length | |
00 01 | line_number_table_length | |
00 00 | start_pc | |
00 07 | line_number |
Class文件的屬性表
00 01
屬性表的大小
SourceFile屬性
00 0D attribute_name_index
00 00 00 02 attribute_length
00 0E sourcefile_index //Test.java