類文件結(jié)構(gòu)
類文件是一組以8位字節(jié)為基礎(chǔ)的二進(jìn)制流睹限,各個數(shù)據(jù)必須嚴(yán)格按照順序排列在類文件中,并且只有兩種數(shù)據(jù)類型
- 無符號數(shù): 描述數(shù)字讯檐、索引引用邦泄、數(shù)量值或者UTF-8編碼的字符串
- 表: 由無符號數(shù)或其它表作為數(shù)據(jù)結(jié)構(gòu)的符合數(shù)據(jù)類型
名稱 | 類型 | 數(shù)量 |
---|---|---|
magic | u4 | 1 |
minor_version | u2 | 1 |
major_version | u2 | 1 |
constant_pool_count | u2 | 1 |
constant_pool | cp_info | constant_pool_count-1 |
access_flag | u2 | 1 |
this_class | u2 | 1 |
super_class | u2 | 1 |
interfaces_count | u2 | 1 |
interfaces | u2 | 1 |
fields_count | u2 | 1 |
field_info | fields | fields_count |
methods_count | u2 | 1 |
methods | methods_info | methods_count |
atrributes_count | u2 | 1 |
atrributes | atrribute_info | atrributes_count |
魔數(shù)和class文件版本
每個class文件頭4個字節(jié)稱為魔數(shù)(magic),用于確定這個class文件是否能被虛擬機(jī)接受裂垦,class文件魔數(shù)為0xCAFEBABE顺囊。
緊接著魔數(shù)后4個字節(jié)是class文件版本號,第5和第6字節(jié)是次版本號(minor_version)蕉拢,第7和第8字節(jié)是主版本號(major_version)
常量池
主版本號之后是常量池入口特碳,常量池是class文件結(jié)構(gòu)中與與其它數(shù)據(jù)關(guān)聯(lián)最多的數(shù)據(jù)類型诚亚。常量池入口有一個u2類型的數(shù)據(jù),代表常量池容量計(jì)數(shù)(constant_pool_count)午乓,這個值從1開始站宗,0有特殊作用,表示在特定情況下不引用任何一個常量池項(xiàng)目益愈。
常量池中主要存放一下兩種常量
- 字面量(Literal): 常量梢灭,如文本字符串和被聲明為final的常量值等
- 符號引用(Symbolic Reference):
- 類和接口的全限定名
- 字段的名稱和描述符
- 方法的名稱和描述符
訪問標(biāo)記
常量池之后是訪問標(biāo)記(access_flag),用于識別一些類或接口的訪問信息
標(biāo)記名稱 | 標(biāo)記值 | 含義 |
---|---|---|
ACC_PUBLIC | 0x0001 | 是否為public |
ACC_FINAL | 0x0010 | 是否為final蒸其,只有類可以設(shè)置 |
ACC_SUPER | 0x0020 | 是否允許使用invokespecial字節(jié)碼指令敏释,JDK 1.2之后為true |
ACC_INTERFACE | 0x0200 | 是否為接口 |
ACC_ABSTRACT | 0x0400 | 是否為abstract類型,接口和抽象類為true摸袁,其它為false |
ACC_SYNTHETIC | 0x1000 | 非用戶代碼產(chǎn)生 |
ACC_ANNOTATION | 0x2000 | 是否為注解 |
ACC_ENUM | 0x4000 | 是否為枚舉 |
類索引钥顽、父類索引和接口索引集合
- 類索引(this_class): 用于確定這個類的全限定名
- 父類索引(super_class)是u2類型: 用于確定這個父類的全限定名
- 接口索引(interfaces_count): 用來描述這個類實(shí)現(xiàn)了哪些接口,是一組u2類型的數(shù)據(jù)集合
字段表集合
- 字段表(field_info): 用于描述接口或類中聲明的變量
- 字段(fields): 包含了類級別變量或?qū)嵗兞靠恐话椒▋?nèi)部聲明的變量
字段表結(jié)構(gòu)
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
access_flags | u2 | 1 | 訪問限定標(biāo)記 |
name_index | u2 | 1 | 對常量池引用蜂大,字段的簡單名字 |
descriptor_index | u2 | 1 | 對常量池引用,字段和方法的描述符 |
attributes_count | u2 | 1 | |
attributes | attributes_info | 1 |
字段訪問標(biāo)志
|ACC_PUBLIC| 0x0001 | 是否為public|
|ACC_PRIVATE| 0x0002 | 是否為private|
|ACC_PROTECTED| 0x0004 | 是否為protected|
|ACC_STATIC| 0x0008| 是否為static|
|ACC_FINAL| 0x0010| 是否為final|
|ACC_VOLATILE| 0x0040| 是否為volitale|
|ACC_TRANSIENT| 0x0080| 是否為transient|
|ACC_SYNTHETIC| 0x1000| 是否由編譯器自動產(chǎn)生|
|ACC_ENUM| 0x4000| 是否為枚舉|
方法表集合
和字段表集合類似
屬性表集合
屬性表(attributes_info)用于描述某些場景專有的信息蝶怔。
名稱 | 使用位置 | 含義 |
---|---|---|
Code | 方法表 | Java代碼變異成的字節(jié)碼指令 |
ConstantValue | 字段表 | final關(guān)鍵定義的常量 |
Deprecated | 類奶浦、方法和字段表 | 被聲明為deprecated的方法和字段 |
Execeptions | 方法表 | 方法跑出的異常 |
InnerClass | 類方法 | 內(nèi)部類列表 |
LineNumberTable | Code屬性 | Java源碼的行號與字節(jié)指令的對應(yīng)關(guān)系 |
LocalVariableTable | Code屬性 | 方法的局部變量描述 |
SourceFile | 類文件 | 源文件名稱 |
Synthetic | 類、方法和字段表 | 表示方法或字段為編譯器自動生成 |
code屬性
Java方法體里的代碼被編譯器處理后最終變成字節(jié)碼存在code屬性內(nèi)
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 指向CONSTANT_Utf8_info常量的索引踢星,固定為Code |
attribute_length | u4 | 1 | 屬性值的長度 |
max_stack | u2 | 1 | 操作棧最大深度财喳,虛擬機(jī)運(yùn)行時需要根據(jù)這個值來分配棧幀的棧深度 |
max_locals | u2 | 1 | 表示局部變量所需的儲存空間,單位是slot斩狱,是虛擬機(jī)為局部變量分配內(nèi)存所使用的最小單位(1 slot = 32bit) |
code_length | u4 | 1 | 字節(jié)碼的長度耳高,雖然是u4,但是字節(jié)碼長度不能超過65535 |
code | u1 | code_length | 儲存字節(jié)碼 |
exception_table_length | u2 | 1 | |
exception_table | exception_info | 1 | |
attribues_count | u2 | 1 | |
attributes | attribute_info | attribues_count |
Exception屬性
用于列舉出方法中可能拋出的受查異常
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | |
attribute_length | u4 | 1 | 屬性值的長度 |
number_of_exceptions | u2 | 1 | |
exception_index_table | u2 | number_of_exceptions |
LineNumberTable屬性
用于描述Java源代碼和字節(jié)碼行號(偏移量)之間的對應(yīng)關(guān)系所踊,不是運(yùn)行時必須的屬性泌枪,如果不生成該屬性就無法再拋出異常時返回代碼中對應(yīng)的行號。
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度 |
line_number_table_Length | u2 | 1 | |
line_number_table | line_number_info | line_number_table_length |
LocalVariableTable屬性
用于描述棧幀中局部變量表中的變量與Java源碼中定義的變量之間的關(guān)系秕岛,不是運(yùn)行時必須的屬性碌燕,如果沒有生成所有參數(shù)名稱都將丟失
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度 |
local_variable_table_Length | u2 | 1 | |
local_variable_table | local\ _variable_info | local_variable_table_length |
local_variable_info結(jié)構(gòu)
名稱 | 類型 | 數(shù)量 | 說明 | |
---|---|---|---|---|
start_pc | u2 | 1 | 這個局部變量聲明周期開始時的字節(jié)碼偏移量 | |
length | u2 | 1 | 這個局部變量聲明周期開始時的字節(jié)碼作用范圍的長度 | |
name_index | u2 | 1 | 指向CONSTANT_Utf8_info常量的索引,代表局部變量的名稱 | |
descriptor_index | 1 | 指向CONSTANT_Utf8_info常量的索引继薛,代表局部變量的描述符 | ||
index | 1 | u2 | 表示這個局部變量在棧幀局部變量中slot的位置 |
SourceFile屬性
用于記錄生成這個class文件源代碼的名稱修壕,是可選的,如果不生成這個屬性遏考,拋出異常時不會顯示出錯代碼的文件名慈鸠。
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度 |
sourcefule_index | u2 | 1 | 指向CONSTANT_Utf8_info常量的索引,常量值時源碼文件的文件名 |
ConstantValue屬性
ConstantValue屬性的作用是通知虛擬機(jī)自動為靜態(tài)變量賦值灌具,只有被static修飾的變量才能用這個屬性
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度 |
constant_value_index | u2 | 1 | 指向常量池的引用 |
InnerClasses屬性
InnerClasses屬性用于記錄內(nèi)部類與宿主類之間的關(guān)聯(lián)青团,如果一個類中有內(nèi)部類譬巫,則會生成InnerClass屬性。
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度 |
nubmber_of_classes | u2 | 1 | 代表記錄多少個內(nèi)部類信息 |
inner_class | inner_class_info | nubmber_of_classes |
inner_class_info
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
inner_class_info_index | u2 | 1 | 指向CONSTANT_Class_info常量的索引督笆,代表內(nèi)部類的符號引用 |
outter_class_info_index | u2 | 1 | 指向CONSTANT_Class_info常量的索引芦昔,代表宿主類的符號引用 |
inner_name_index | u2 | 1 | 指向CONSTANT_Utf8_info常量的索引,代表這個內(nèi)部類的名稱娃肿,如果是匿名內(nèi)部類則為0 |
inner_name_access_flag | u2 | 1 | 內(nèi)部類的訪問標(biāo)志 |
Deprecated屬性
表示某個類咕缎、字段或方法不再推薦使用
Synthetic屬性
表示該字段和方法是不是有Java源碼直接生成的
名稱 | 類型 | 數(shù)量 | 說明 |
---|---|---|---|
attribute_name_index | u2 | 1 | 屬性值的索引 |
attribute_length | u4 | 1 | 屬性值的長度,值必須為0x00000000 |
參考
- 深入理解Java虛擬機(jī), 周志明