Java class文件结构
Java 文件
1 | package com.footmanff.jdktest.base; |
javap
1 | Classfile /private/tmp/TestClass.class |
class 文件 16 进制输出
(jdk 1.8.0_131):
1 | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
比如第 1 行第 1 列的值为 ca,就标记为 <1, 0>。
以上一个字符表示一个 16 进制数,两个 16 进制数其实代表的其实就是一个字节。每个空格分割的都是两个字节(1 字节 8 位)。然后逐个字节去分析 class 文件格式。
u1 代表 1 个字节,依次类推,u4 代表 4 字节
class 文件格式
魔数
第 1 行,cafe babe
次版本号
第 1 行,0000,10 进制为 0
主版本号
第 1 行,0034,10 进制为 52。结合次版本号,最终 class 版本号是 52.0
常量池常量数量
第 1 行,0016,10 进制为 22。
常量池表(constant_pool_count & constant_pool)
![2018-02-11 at 3.09 PM](/var/folders/fd/ptrbg3sx0cv0k988y2qdqxnm0000gn/T/se.razola.Glui2/220A95B8-E822-4BBC-A22F-28BE92891D60-769-00005B6A513F5A86/2018-02-11 at 3.09 PM.png)
常量池表的索引从 1 开始,比如 constant_pool_count 为 22,索引表的下标范围是 1 - 21。0 是预留出来的(TODO)
从第 1 行 0a00 开始,0a 代表,依次:
索引 | 类型 | tag | ||
---|---|---|---|---|
1 | constant_methodref_info | 0A | 00 04: 00 12: |
|
2 | constant_fieldref_info | 09 | 00 03: 00 13: |
|
3 | constant_class_info | 07 | 00 14: | |
4 | constant_class_info | 07 | 00 15: | |
5 | constant_utf8_info | 01 | 00 01:字节长度 length 6D:length 个字节,这里是 1 字节,utf8字符为「m」 |
m |
6 | constant_utf8_info | 01 | 00 01: 49:length 个字节,这里是 1 字节,utf8字符为「I」 |
I |
7 | constant_utf8_info | 01 | 00 06: 3c:< 69:i 6e:n 69:i 74:t 3e:> |
|
8 | constant_utf8_info | 01 | 00 03: 28:( 29:) 56:V |
()V |
9 | constant_utf8_info | 01 | 0004 43 6f 64 65 |
Code |
10 | constant_utf8_info | 01 | 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 |
LineNumberTable |
11 | constant_utf8_infoconstant_utf8_info | 01 | 00 12:18 个字节 4c 6f 63 61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 |
LocalVariableTable |
12 | constant_utf8_info | 01 | 00 04 74 68 69 73 |
|
13 | constant_utf8_info | 01 | 00 26:38 4c 63 6f 6d 2f 66 6f 6f 74 6d 61 6e 66 66 2f 6a 64 6b 74 65 73 74 2f 62 61 73 65 2f 54 65 73 74 43 6c 61 73 73 3b |
Lcom/footmanff/jdktest/base/TestClass; |
14 | constant_utf8_info | 01<9, f> | 00 03 69 6e 63 |
inc |
15 | constant_utf8_info | 01 | 00 03 28 29 49 |
()I |
16 | constant_utf8_info | 01 | 00 0a:10 53 6f 75 72 63 65 46 69 6c 65 |
SourceFile |
17 | constant_utf8_info | 01 | 00 0e:14 54 65 73 74 43 6c 61 73 73 2e 6a 61 76 61 |
TestClass.java |
18 | constant_nameAndType_info | 0c | 00 07 00 08 |
|
19 | constant_nameAndType_info | 0c | 00 05 00 06 |
|
20 | constant_utf8_info | 01 | 00 24:36 63 6f 6d 2f 66 6f 6f 74 6d 61 6e 66 66 2f 6a 64 6b 74 65 73 74 2f 62 61 73 65 2f 54 65 73 74 43 6c 61 73 73 |
com/footmanff/jdktest/base/TestClass |
21 | constant_utf8_info | 01 | 00 10:16 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 |
java/lang/Object |
access_flags
00 21
this_class
00 03
super_class
00 04
interfaces_count
00 00<17, 4>
interfaces
因为 interfaces_count 为 0,所以这里一个都没有
fields_count
00 01
fields
access_flag | name_index | descriptor_index | attribute_count | attributes |
---|---|---|---|---|
00 02 private |
00 05 常量池索引 5:m |
00 06 常量池索引 6:I I (基本类型 int 用大写的 i 代表) |
00 00 属性数量为0 |
无 |
method_count
00 02
methods
access_flag | name_index | descriptor_index | attribute_count | attributes |
---|---|---|---|---|
00 01 | 00 07 常量池索引 7: |
00 08 常量池索引 8:()V |
00 01 1 个属性 |
00 09:常量池索引 9 -> Code 00 00 00 2f:47 字节的方法代码 |
、 TODO
code ( init )
code 内存的是方法的字节码,从 <18, 9> 到 <21, 7>,连 attribute_name_index 和 attribute_length 一共 47 字节,所以字节码部分一共 41 字节,如下:
1 | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
属性表结构:
Code 属性:
max_stack
是操作数栈的最大深度 00 01
max_locals
局部变量表需要空间,单位 slot,00 01
code_length
字节码的字节长度 00 00 00 05
code
字节码的二进制流,每个指令是一个字节,2a b7 00 01 b1
exception_table_length
异常表长度
exception_table
异常表