該文章是再次讀《深入理解java虛擬機(jī)》6.3章class類文件的結(jié)構(gòu)的學(xué)習(xí)記錄
使用javac -target 1.6
將下列代碼編譯為字節(jié)碼文件
package org.fenixsoft.clazz;
public class TestVersion {
private int m;
public int inc(){
return m + 1;
}
}
字節(jié)碼文件可以通過vscode+hexdump插件來(lái)查看,內(nèi)容如下
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 32 00 13 0A 00 04 00 0F 09 J~:>...2........
00000010: 00 03 00 10 07 00 11 07 00 12 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 03 69 6E 63 umberTable...inc
00000050: 01 00 03 28 29 49 01 00 0A 53 6F 75 72 63 65 46 ...()I...SourceF
00000060: 69 6C 65 01 00 10 54 65 73 74 56 65 72 73 69 6F ile...TestVersio
00000070: 6E 2E 6A 61 76 61 0C 00 07 00 08 0C 00 05 00 06 n.java..........
00000080: 01 00 1F 6F 72 67 2F 66 65 6E 69 78 73 6F 66 74 ...org/fenixsoft
00000090: 2F 63 6C 61 7A 7A 2F 54 65 73 74 56 65 72 73 69 /clazz/TestVersi
000000a0: 6F 6E 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F on...java/lang/O
000000b0: 62 6A 65 63 74 00 21 00 03 00 04 00 00 00 01 00 bject.!.........
000000c0: 02 00 05 00 06 00 00 00 02 00 01 00 07 00 08 00 ................
000000d0: 01 00 09 00 00 00 1D 00 01 00 01 00 00 00 05 2A ...............*
000000e0: B7 00 01 B1 00 00 00 01 00 0A 00 00 00 06 00 01 7..1............
000000f0: 00 00 00 03 00 01 00 0B 00 0C 00 01 00 09 00 00 ................
00000100: 00 1F 00 02 00 01 00 00 00 07 2A B4 00 02 04 60 ..........*4...`
00000110: AC 00 00 00 01 00 0A 00 00 00 06 00 01 00 00 00 ,...............
00000120: 06 00 01 00 0D 00 00 00 02 00 0E ...........
根據(jù)書中所寫照瘾,Class文件格式如下
類型 | 名稱 | 數(shù)量 |
---|---|---|
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_poll_count | 1 |
cp_info | constant_poll | constant_poll_count |
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 |
需要注意的是method_info和field_info中都可能有attribute_info匈棘,而且類文件的結(jié)尾也是attribute_info的集合。
按照上面Class文件結(jié)構(gòu)可以將上面的字節(jié)文件分為下面結(jié)構(gòu)
CA FE BA BE // magic
00 00 00 32 // version
00 13 // constant_pool_count
// 常量池共19-1個(gè)常量析命,常量計(jì)數(shù)從1而不是從0開始
1 0A 00 04 00 0F // CONSTANT_Methodref_info tag u1 index u2 index u2
2 09 00 03 00 10 // CONSTANT_Fieldref_info tag u1 index u2 index u2
3 07 00 11
4 07 00 12 // CONSTANT_Class_info tag u1 index u2
5 01 00 01 6D // CONSTANT_Utf8_info tag u1 length u2 bytes u1
6 01 00 01 49 // CONSTANT_Utf8_info tag u1 length u2 bytes u1
7 01 00 06 3C 69 6E 69 74 3E // 對(duì)應(yīng)字符串為<init>
8 01 00 03 28 29 56 // 對(duì)應(yīng)字符串()V
9 01 00 04 43 6F 64 65 // 對(duì)應(yīng)字符串為Code
10 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 // 對(duì)應(yīng)字符串為L(zhǎng)ineNumberTable
11 01 00 03 69 6E 63 // 對(duì)應(yīng)字符串為inc
12 01 00 03 28 29 49 // 對(duì)應(yīng)字符串為()I
13 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 // 對(duì)應(yīng)字符串為SourceFile
14 01 00 10 54 65 73 74 56 65 72 73 69 6F 6E 2E 6A 61 76 61 // 對(duì)應(yīng)字符串為TestVersion.java
15 0C 00 07 00 08 // CONSTANT_NameAndType_info tag u1 index u2 index u2
16 0C 00 05 00 06
17 01 00 1F 6F 72 67 2F 66 65 6E 69 78 73 6F 66 74 2F 63 6C 61 7A 7A 2F 54 65 73 74 56 65 72 73 69 6F 6E // 對(duì)應(yīng)字符串為 類的全限定名主卫,即org.fenixsoft.clazz.TestVersion
18 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 // 對(duì)應(yīng)字符串為 Object的類名逃默,即java.lang.Object
// 常量池結(jié)束
00 21 // access_flags 八個(gè)標(biāo)志位來(lái)識(shí)別這個(gè)類的訪問信息, 0021 = 0020 + 0001 ACC_SUPPER 和 ACC_PUBLIC
00 03 // this_class
00 04 // super_class
00 00 // interface_count
// interafces 因?yàn)樯厦鏋?因此這里不存在
00 01 // fields_count
00 02 00 05 00 06 00 00 // fields队秩,因?yàn)楹髢晌槐硎綼ttributes_count為0笑旺,所以不存在attributes
00 02 // methods_count
// 一共兩個(gè)方法
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 // 該方法對(duì)應(yīng)的<init>方法
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 06 // 該方法對(duì)應(yīng)我們寫的inc方法。這兩個(gè)方法都對(duì)應(yīng)了一個(gè)LineNumberTable的屬性馍资,該屬性包含了該方法在Class文件中的行號(hào)
00 01 // attributes_count
00 0D 00 00 00 02 00 0E // SouceFile屬性