该文章是再次读《深入理解java虚拟机》6.3章class类文件的结构的学习记录
使用javac -target 1.6
将下列代码编译为字节码文件
package org.fenixsoft.clazz;
public class TestVersion {
private int m;
public int inc(){
return m + 1;
}
}
字节码文件可以通过vscode+hexdump插件来查看,内容如下
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 ...........
根据书中所写,Class文件格式如下
类型 | 名称 | 数量 |
---|---|---|
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,而且类文件的结尾也是attribute_info的集合。
按照上面Class文件结构可以将上面的字节文件分为下面结构
CA FE BA BE // magic
00 00 00 32 // version
00 13 // constant_pool_count
// 常量池共19-1个常量,常量计数从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 // 对应字符串为<init>
8 01 00 03 28 29 56 // 对应字符串()V
9 01 00 04 43 6F 64 65 // 对应字符串为Code
10 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 // 对应字符串为LineNumberTable
11 01 00 03 69 6E 63 // 对应字符串为inc
12 01 00 03 28 29 49 // 对应字符串为()I
13 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 // 对应字符串为SourceFile
14 01 00 10 54 65 73 74 56 65 72 73 69 6F 6E 2E 6A 61 76 61 // 对应字符串为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 // 对应字符串为 类的全限定名,即org.fenixsoft.clazz.TestVersion
18 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 // 对应字符串为 Object的类名,即java.lang.Object
// 常量池结束
00 21 // access_flags 八个标志位来识别这个类的访问信息, 0021 = 0020 + 0001 ACC_SUPPER 和 ACC_PUBLIC
00 03 // this_class
00 04 // super_class
00 00 // interface_count
// interafces 因为上面为0因此这里不存在
00 01 // fields_count
00 02 00 05 00 06 00 00 // fields,因为后两位表示attributes_count为0,所以不存在attributes
00 02 // methods_count
// 一共两个方法
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 // 该方法对应的<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 // 该方法对应我们写的inc方法。这两个方法都对应了一个LineNumberTable的属性,该属性包含了该方法在Class文件中的行号
00 01 // attributes_count
00 0D 00 00 00 02 00 0E // SouceFile属性
网友评论