天天看點

Java位元組碼(.class檔案)格式詳解(二)

2.9   methods

methods數組記錄了類或接口中的所有方法,包括執行個體方法、靜态方法、執行個體初始化方法和類初始化方法,但不包括父類或父接口中定義的方法。methods數組中每項都是method_info類型值,它描述了方法的詳細資訊,如名稱、描述符、方法中的attribute(如code attribute記錄了方法的位元組碼)等。

method_info

type

descriptor

remark

u2

access_flags

記錄方法的通路權限。見2.9.1

name_index

constant_pool中的索引,constant_utf8_info類型。指定方法名稱。

descriptor_index

constant_pool中的索引,constant_utf8_info類型,指定方法的描述符(見附錄c)。

attributes_count

attributes包含的項目數。

attribute_info

attributes[attributes_count]

字段中包含的attribute集合。見2.9.2-2.9.11

注:methods數組同樣有和fields數組一樣的問題,包括fields中項和constant_methodref_info以及constant_interfacemethodref_info中的差別。以及設計上的問題。詳見field_info中的注。

2.9.1    方法通路權限

方法的通路權限

flag name

value

remarks

acc_public

0x0001

pubilc,包外可通路。

acc_private

0x0002

private,隻可在類内通路。

acc_protected

0x0004

protected,類内和子類中可通路。

acc_static

0x0008

static,靜态。

acc_final

0x0010

final,不可被重寫。

acc_synchronized

0x0020

synchronized,同步方法。

acc_bridge

0x0040

bridge方法,由編譯器生成。(什麼是bridge方法?)

acc_varargs

0x0080

包含不定參數個數的方法。

acc_native

0x0100

native,非java語言實作的方法。(如何實作native方法?)

acc_abstract

0x0400

abstract,抽象方法。

acc_strict

0x0800

strictfp,設定floating-point模式為fp-strict。(什麼是fp-strict模式?)

acc_synthetic

0x1000

synthetic,由編譯器産生,不存在于源代碼中。

注:接口中的方法必須同時設定:acc_public、acc_abstract。設定了acc_abstract後,不可以再設定acc_final、acc_static、acc_private、acc_native、acc_synchronized 、acc_strict。

2.9.2    code attribute (jvm識别)

每個非abstract、非native方法的attributes集合都包含有且僅有一項code attribute。它包含了一個方法的棧、局部變量、位元組碼以及和代碼相關的attribute資訊。

code attribute

attribute_name_index

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“code”)。

u4

attribute_length

該attribute内容的位元組長度。

max_stack

該方法操作棧的最大深度。

max_locals

該方法調用時需要配置設定的局部變量的最大個數,包括該方法的參數。

code_length

該方法位元組碼長度(以位元組為機關)

u1

code[code_length]

存放位元組碼數組(位元組碼如何解析?)。

exception_table_length

異常表的長度。

exception_table_info

每個表項記錄一段異常處理代碼資訊和範圍。

start_pc

記錄應用該項異常處理的起始位元組碼。在位元組碼數組中的起始索引号[start_pc, end_pc)。索引号必須是opcode(一條指令的開始位置)對應的位置。

end_pc

handler_pc

記錄該項異常處理代碼的開始位址。在位元組碼數組中的開始索引号。索引号必須是opcode對應的位置。

catch_type

constant_pool中的索引,constant_class_info類型。指定該項能捕獲的異常類(或其子類)。或0用于實作finally文法(即不管什麼類型都會捕獲。)

exception_table[exception_table_length]

字段中包含的attribute集合。見2.9.2.1-2.9.2.4

2.9.2.1 stackmaptable attribute (jvm識别)

stackmaptable attribute在j2se 6中引入,記錄了類型檢查時需要用到的資訊,如位元組碼的偏移量、局部變量的驗證類型、操作棧中的驗證類型,用于類型檢查過程。在code attribute隻能包含一項stackmaptable attribute,記錄所有目前code attribute中的驗證資訊。

一項stackmaptable attribute中包含多項stack_map_frame。每項stack_map_frame顯式或隐式得記錄了位元組碼的偏移量、局部變量驗證類型和操作棧的驗證類型。驗證器就是通過擷取局部變量類型和操作棧類型進行驗證的(具體如何驗證呢?)。

在stack_map_frame中,并不是直接記錄了位元組碼的索引值,而是記錄了offset_delta的值。stack_map_frame中的每一項都通過前一項的值+1+offset_delta計算出目前項對應的真正的位元組碼的位置,隻有當目前stack_map_frame的前一項是目前方法的初始幀(initial frame of the method,什麼是方法的初始幀?)的時候,offset_delta的值才直接表示位元組碼位置。

(為什麼不直接記錄位元組碼的索引值?為了保證stack_map_frame被正确的排序了。為什麼要加1再加offset_delta?為了避免重複出現stack_map_frame項。)

stackmaptable attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“stackmaptable”)。

number_of_entries

stack_map_frame項的數目。

stack_map_frame(union,聯合體類型)

每一項顯式或隐式得記錄了位元組碼的偏移量、局部變量驗證類型和操作棧的驗證類型。每一項第一個位元組指定目前stack_map_frame的類型(tag)

same_frame

same_frame {

     u1 frame_type = same; /* 0-63 */

}

tag的值為[0-63]。offset_delta = frame_type。表示目前幀和前一幀有相同的局部變量,并且目前操作數棧為空。

same_locals_1_stack

_item_frame

same_locals_1_stack_item_frame {

u1 frame_type = same_locals_1_stack_item; /* 64-127 */

     verification_type_info stack[1]

tag值為[64-127]。offset_delta = frame_type – 64。表示目前幀和前一幀有相同的局部變量,并且操作棧内的操作數條目數為1,因而它為該操作數棧内的操作數儲存了一項verification_type_info(詳見下表)。([128-246]的tag值保留)

_item_frame_extended

same_locals_1_stack_item_frame_extended {

     u1 frame_type = sam_locals_1_stack_item_exteneded; /* 247 */

     u2 offset_delta;

     verification_type_info stack[1];

tag值為247。offset_delta = offset_delta。表示目前值幀和前一幀有相同的局部變量,并且操作棧内的操作數條目數為1,因而它為該操作數棧内的操作數儲存了一項verification_type_info(詳見下表)。和上一類型的差別是這裡的offset_delta是直接給出的。

chop_frame

chop_frame {

     u1 frame_type = chop; /* 248 – 250 */

tag值為[248, 250]。offset_delta = offset_delta。表示目前操作棧為空,而目前局部變量比前一幀的局部變量少後面的251 – frame_type個局部變量。

same_frame_extended

same_frame_extended {

     u1 frame_type = same_frame_extended; /* 251 */

tag值為251。offset_delta = offset_delta。表示目前幀和前一幀有相同的局部變量,并且操作數棧為空。和samep_frame的差別是same_frame_extended中的offset_delta值直接給出。

append_frame

append_frame {

     u1 frame_type = append; /* 252 – 254 */

     verification_type_info locals[frame_type – 251];

tag值為[252-254]。offset_delta = offset_delta。表示操作數棧為空,而目前幀的局部變量比前一幀的局部變量多frame_type – 251個。因而它也定義了frame_type – 251項的verification_type_info類型。詳見下表。

full_frame

full_frame {

     u1 frame_type = full_frame; /* 255 */

     u2 number_of_locals;

     verification_type_info locals[number_of_locals];

     u2 number_of_stack_items;

     verification_type_info stack[number_of_stack_items];

tag值255。offset_delta = offset_delta。full_frame則定義了所有的資訊,包括offset_delta的值,以及目前幀和前一幀不同的所有局部變量和操作數。locals[0]表示0号局部變量;stack[0]表示棧底操作數。

entries[number_of_entries]

verification_type_info(union,聯合體類型)

記錄位元組碼的驗證類型。每一項第一個位元組指定驗證類型(tag)。

top_variable_info

top_variable_info {

    u1 tag = item_top; /* 0 */

指定局部變量的驗證類型為top。

integer_variable_info

integer_variable_info {

    u1 tag = item_integer; /* 1 */

指定驗證類型為int。

float_variable_info

float_variable_info {

    u1 tag = item_float; /* 2 */

指定驗證類型為float。

long_variable_info

long_variable_info {

    u1 tag = item_long; /* 4 */

指定驗證類型為long。

double_variable_info

double_variable_info {

    u1 tag = item_double; /* 3 */

指定驗證類型為double。

null_variable_info

null_variable_info {

    u1 tag = item_null; /* 5 */

指定驗證類型為null。

uninitializedthis_variable_info

uninitializedthis_variable_info {

    u1 tag = item_uninitializedthis; /* 6 */

指定驗證類型為uninitializedthis(什麼是uninitializedthis?)。

object_variable_info

object_variable_info {

u1 tag = item_object; /* 7 */

u2 cpool_index; //constant_pool索引,constant_class_info類型。

指定驗證類型為cpool_index中指定的類型執行個體。

uninitialized_variable_info

uninitiated_variable_info {

u1 tag = item_uninitialized; /* 8 */

u2 offset;

指定驗證類型為uninitialized(這種類型是指什麼?)。offset記錄了用于建立執行個體的new指令的偏移量。(the offset item indicates the offset of the new instruction that created the object being stored in the location.這段話是什麼意思?)

注:對驗證過程不太了解,因而stackmaptable attribute的一些描述也沒能了解。

2.9.2.2 linenumbertable attribute (調試資訊)

linenumbertable attribute用于調試器,以擷取某條指令對應的源代碼中的行号。多條指令可以對應相同的行号。

linenumbertable attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“linenumbertable”)。

line_number_table_length

line_number_table

一條指令和源代碼行号的映射關系表。

一條指令的開始索引(位元組碼數組中的索引号)

line_number

源代碼中的行号。

line_number_table[line_number_table_length]

2.9.2.3 localvariabletable attribute (調試資訊)

localvariabletable attribute用于調試器,以擷取在方法運作時局部變量的資訊。在一個code attribute中隻包含1或0項localvariabletable attribute。

localvariabletable attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“localvariabletable”)。

local_variable_table_length

局部變量表的長度。

local_variable_table

每項記錄了一個局部變量有值的範圍和該局部變量在局部變量數組中的索引值。

記錄該局部變量的有值範圍,位元組碼數組中的索引範圍[start_pc, start_pc+length)。

length

constant_pool中索引,constant_utf8_info類型,記錄該項代表的局部變量名。

constant_pool中索引,constant_utf8_info類型,記錄該項代表的局部變量的字段描述符(見附錄c)。

index

記錄該項代表的局部變量在方法的局部變量數組中的索引。

local_variable_table[local_variable_table_length]

2.9.2.4 localvariabletypetable attribute (調試資訊)

localvariabletypetable attribute用于調試器,以擷取在方法運作時泛型局部變量的資訊。在一個code attribute中隻包含1或0項localvariabletypetable attribute。

localvariabletable attribute和localvariabletypetable attribute表達的資訊是類似的,他們的差別是對泛型類型的局部變量,需要用signature的形式表達,而不能僅僅用descriptor的形式表達,因而對泛型類型的局部變量,需要在localvariabletable attribute和localvariabletypetable attribute中同時存在一項;而對非泛型類型的局部變量來說,隻要在localvariabletable attribute存在表項就可以了。

從這裡我們也可以看出泛型是後期才被位元組碼所支援的痕迹。我感覺很奇怪的是java在設計的時候,泛型應該已經開始流行了,為什麼它在設計之初沒有把它考慮進去,而要到後期加入,然後讓這種修補的設計做的那麼糟糕呢,java的設計者如果能在設計的時候把它作為擴充考慮,然後再後期去實作,不是更好嗎?

localvariabletypetable attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“localvariabletypetable”)。

local_variable_type_table_length

泛型局部變量表的長度。

local_variable_type_table

每項記錄了一個泛型局部變量有值的範圍和該局部變量在局部變量數組中的索引值。

signature_index

constant_pool中索引,constant_utf8_info類型,記錄該項代表的局部變量的字段簽名(見附錄d)。

local_variable_type_table[local_variable_table_length]

2.9.3    exceptions attribute (jvm識别)

exceptions attribute記錄了一個方法需要檢驗的異常類型。一個method_info的attributes中隻能包含一項exceptions attribute。即記錄一個方法可以抛出的異常類型。

一個方法可以抛出的異常類型遵循三點:

1. 抛出的異常是runtimeexception類型或其子類。

2. 抛出的異常是error類型或其子類。

3. 抛出的異常是exceptions attribute中記錄的類型或它們的子類。

exceptions attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“exceptions”)。

number_of_exceptions

exception_index_table表項長度

exception_index_table[number_of_exceptions]

每項為constant_pool中的索引,constant_class_info類型。記錄該方法可抛出的異常類型。

2.9.4    runtimevisibleparameterannotations attribute

runtimevisibleparameterannotations attribute記錄該方法在運作時可見的修飾該方法參數的annotation,進而java程式可以通過反射機制擷取這些annotation中的值。一個method_info中的attributes中隻能包含一項runtimevisibleannotations attribute。

runtimevisibleannotations attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“runtimevisibleannotations”)。

num_parameters

記錄該方法中參數個數

parameter_annotations

每個參數和在它之上定義的annotations的映射表。順序和源碼定義順序一緻。

num_annotations

記錄該參數定義的annotation的個數

annotation

annotations[num_annotations]

記錄該項對應的參數中所有運作時可見的annotaion項,順序和源碼定義順序一緻。(annotation類型見附件e)

parameter_annotations[num_parameters]

注:從該資料結構的定義中可以看到,java對parameter annotation存放的資訊是很少的,我們隻能依賴于定義的順序來擷取這些annotation,而不能通過參數名或者參數類型來擷取相應的annotation。事實上,

1.       由于參數名的資訊隻在調試時才有,如localvariabletable attribute或localvariabletypetable attribute中;

2.       而一個方法中不同參數的類型極有可能是相同的;

因而從邏輯上來說,通過參數名或者參數類型傳回相應的annotation資訊的方式也是不合理的。由于這個原因,在java.lang.reflect.method類的方法中也隻是給出了:

annotation[][] getparameterannotations()

的方法,獲得所有參數中的annotation,這裡的二維數組一維代表參數,一維代表多個annotation,它們的順序和源碼定義時順序相同。

2.9.5    runtimeinvisibleparameterannotations attribute

runtimeinvisibleparameterannotations attribute記錄該方法在運作時不可見的修飾該方法參數的annotation。一個method_info中的attributes中隻能包含一項runtimeinvisibleannotations attribute。

runtimeinvisibleparameteranotations attribute和runtimevisibleannotations attribute的差別在于:

後者中的annotation預設情況下,可以通過java提供的反射函數擷取相應的annotation,而前者的annotation在預設情況下是無法通過java提供的反射函數被擷取的,而需要通過特定的機制(如設定jvm的特定參數,該機制由不同的jvm實作來決定)才能通過java提供的反射函數擷取内部的annotation。

然而這樣就又有一個問題了,runtimeinvisibleparameteranotations attribute是如何被填入值的呢?通過什麼機制讓源碼中方法參數的annotation是預設不可見的呢?我感覺這個也可能也是由不同編譯器提供不同的機制來實作的,不知道sun提供的編譯器有沒有什麼機制支援它了??

runtimeinvisibleannotations attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“runtimeinvisibleannotations”)。

記錄該項對應的參數中所有運作時不可見的annotaion項,順序和源碼定義順序一緻。(annotation類型見附件e)

2.9.6    annotationdefault attribute

annotationdefault attribute用于annotation類型方法中,以記錄該方法所代表的annotation類型的預設值。每個annotation類型的method_info中的attributes中隻能包含一個annotationdefault attribute項。如:

@retention(retentionpolicy.runtime)

@target({elementtype.method, elementtype.parameter})

public @interface test {

    public int id() default -1;

    public string description() default "no description";

該annotation類産生的class二進制檔案中的id方法和description方法的attributes數組中都會包含一項annotationdefault attribute,它們的預設值分别為-1(constant_integer_info類型)和”no description”(constant_string_info類型)。

annotationdefault attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“annotationdefault”)。

element_value

default_value

記錄該方法表示的annotation類型的預設值。(element_value結構詳見附錄e)

2.9.7    synthetic attribute

參見2.11.1

2.9.8    signature attribute

參見2.11.2

2.9.9    deprecated attribute

參見2.11.3

2.9.10    runtimevisibleannotations attribute

參見2.11.4

2.9.11    runtimeinvisibleannotations attribute

參見2.11.5

2.10 attributes

attributes數組記錄了和類或接口相關的所有attribute項(和字段相關的attribute在field_info的attributes中,和方法相關的attribute在method_info的attrubutes中,和位元組碼相關的attribute在code attribute的attributes中)。attributes數組中的每項都是attribute_info類型,它描述了attribute的名稱、詳細資訊等。該attributes數組描述了classfile的一些額外資訊。jvm必須忽略它不能識别的attribute,而且那些jvm不能識别的的attribute也不能影響class檔案的語義。

目前定義的attribute有:code attribute、constant value attibute、deprecated attribute、enclosing method attribute、exceptions attribute、inner classes attribute、line number table attribute、local variable table attribute、local variable type table attribute、runtime visible annotations attribute、runtime invisible annotation attribute、runtime visible parameter annotation attribute、runtime invisible parameter annotation attribute、signature attribute、source debug extension attribute、source file attribute、stack map table attribute、synthetic attribute、annotation default attribute等。它們有些隻存在于field_info中,有些隻存在method_info中,有些隻存在classfile中,有些隻存在于code attribute中,還有些可以同時存在于field_info、method_info、classfile中。

attribute結構隻存在與classfile、method_info、field_info、code attribute結構中。

attribute_info(attribute的基本資料結構)

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱。

info[attribute_length]

記錄attribute的内容位元組資料。

在使用者自定義的編譯器或者java虛拟機中可以擴充classfile中的attribute表(即自定義新的attribute)。但是對自定義的attribute必須遵循一些規則:

1.       使用者自定義的新的attribute(非sun定義的attribute)命名必須是遵循java命名規則,即加入公司的包名資訊,如:“com.levin.new_attribute”

2.       新增的attribute隻可以作為輔助的資訊,如增加和自定義調試器相關的調試資訊,但是它們不可以改變classfile的語義。什麼叫改變classfile的語義呢?我現在的了解,比如在自定義的java虛拟機中,為某個方法新增一個attribute,用以标記該方法在運作是不可以被調用。不知道這個例子合适不合适。

3.       對于自定義的java虛拟機,禁止因為某些它不識别的attribute存在而抛出異常或者直接報錯。但是這一層限制可以加載自定義編譯器中。java虛拟機必須忽略它不識别的attribute。

以下是定義在classfile中的attribute。

2.10.1     innerclasses attribute

innerclasses記錄目前類的所有内部類。目前類需要記錄的内部類的算法如下:

1. 目前類中定義的内部類,包括方法中定義的類。

2. 如果目前類本身是内部類,則還要記錄目前類的外部類,直到外部類不是一個内部類。

如:

class outer {

    public class inner {

       public void getmethod() {

           class inner3 {

              class inner4 {

              }

           }

       }

       public class inner2 {

           public class inner5 {

    }

    public class inner_1 {

outer中的innerclasses attribute:

    [inner class info: #17 org/levin/insidejvm/miscs/instructions/outer$inner, outer class info: #1 org/levin/insidejvm/miscs/instructions/outer

     inner name: #19 inner, accessflags: 1 public],

    [inner class info: #20 org/levin/insidejvm/miscs/instructions/outer$inner_1, outer class info: #1 org/levin/insidejvm/miscs/instructions/outer

     inner name: #22 inner_1, accessflags: 1 public]

inner中的innerclasses attribute:

    [inner class info: #1 org/levin/insidejvm/miscs/instructions/outer$inner, outer class info: #23 org/levin/insidejvm/miscs/instructions/outer

     inner name: #25 inner, accessflags: 1 public],

    [inner class info: #26 org/levin/insidejvm/miscs/instructions/outer$inner$1inner3, outer class info: #0

     inner name: #28 inner3, accessflags: 16 final],

    [inner class info: #29 org/levin/insidejvm/miscs/instructions/outer$inner$inner2, outer class info: #1 org/levin/insidejvm/miscs/instructions/outer$inner

     inner name: #31 inner2, accessflags: 1 public]

inner5中的innerclasses attribute:

    [inner class info: #22 org/levin/insidejvm/miscs/instructions/outer$inner, outer class info: #24 org/levin/insidejvm/miscs/instructions/outer

     inner name: #26 inner, accessflags: 1 public],

    [inner class info: #27 org/levin/insidejvm/miscs/instructions/outer$inner$inner2, outer class info: #22 org/levin/insidejvm/miscs/instructions/outer$inner

     inner name: #29 inner2, accessflags: 1 public],

    [inner class info: #1 org/levin/insidejvm/miscs/instructions/outer$inner$inner2$inner5, outer class info: #27 org/levin/insidejvm/miscs/instructions/outer$inner$inner2

     inner name: #30 inner5, accessflags: 1 public]

innerclasses attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“innerclasses”)。

number_of_classes

記錄内部類的數量。

classes

定義每項inner class的資訊。

inner_class_info_index

constant_pool中的索引,constant_class_info類型。記錄内部類名。

outer_class_info_index

若目前項内部類不是包含它的類的成員類,則該值為0;否則該值為constant_pool中的索引,constant_class_info類型,記錄外部類名。

inner_name_index

若目前項的内部類為匿名類,則該值為0;否則該值為constant_pool中的索引,constant_utf8_info類型,記錄該内部類的簡單名(沒有字首)。

inner_class_access_flags

定義目前項的内部類的通路屬性。見下表。

classess[number_of_classes]

注:為什麼需要為内部類保留那麼多的資訊呢?是為了在反射的時候擷取必要的資訊或者在反編譯的時候可以更好的還原源代碼的結構嗎?還是有其他的作用?

内部類的通路權限

pubilc,類外可通路。

private,類内才可通路。

protected,類和其子類可通路。

static,靜态内部類。

final,不能有子類。

acc_interface

0x0200

接口,同時需要設定:acc_abstract。不可同時設定:acc_final、acc_super、acc_enum

抽象類,無法執行個體化。不可和acc_final同時設定。

acc_annotation

0x2000

注解類型(annotation),需同時設定:acc_interface、acc_abstract

acc_enum

0x4000

枚舉類型

2.10.2     enclosingmethod attribute

當且僅當一個類是匿名類或者本地類(local class),該類才會包含一項且僅有一項enclosingmethod attribute。

然而什麼是本地類(local class)呢?我的了解,所謂本地類就是在方法内部定義的類,如以下類的定義:

class a {

    public iterator getiterator() {

       class localclass {

       return new iterator() {

           public boolean hasnext() { return false; }

           public object next() { return null; }

           public void remove() { }

       };

匿名類a$1.class中的enclosingmethod attribute:

 enclosing method: #29 #31 org/levin/insidejvm/miscs/instructions/a.getiterator()ljava/util/iterator;

本地類a$1localclass.class中的enclosingmethod attribute:

 enclosing method: #22 #24 org/levin/insidejvm/miscs/instructions/a.getiterator()ljava/util/iterator;

enclosingmethod attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“enclosingmethod”)。

該attribute内容的位元組長度(4)。

class_index

constant_pool中的索引,constant_class_info類型。記錄定義目前類所在方法的宿主類。如上例中,a$1.class和a$1localclass.class中的class_index都指向類a。

method_index

若目前類沒有被方法方法包含,如目前類是指派給類成員的匿名類,則method_index值為0,否則該method_index的值為constant_pool中的索引,constant_nameandtype_info類型。記錄了class_index指定的類中定義的包含目前類的方法名和類型資訊。

注:這裡同樣也有一個問題,就是enclosingmethod attribute存在的目的問題。我現在的了解,該attribute的存在也應該隻是為了用于反射資訊和反編譯時可以更好的還原原來代碼的結構,在虛拟機運作該程式的時候,由于所有的指令已經編譯好了,虛拟機應該不需要這些資訊。但是事實是這樣的嗎?有待考證。

2.10.3     sourcefile attribute

sourcefile attribute用于記錄和目前位元組碼對應的源代碼的檔案(由編譯器産生,該attribute隻是記錄相應源代碼的檔案名,而不記錄和路徑相關的資訊)。一個classfile中隻能包含一項sourcefile attribute。

sourcefile attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute的名稱(“sourcefile”)。

該attribute内容的位元組長度(2)。

sourcefile_index

constant_pool中的索引,constant_utf8_info類型。記錄相應的源代碼檔案名。

2.10.4     sourcedebugextension attribute

sourcedebugexctension attribute是java為調試時提供的擴充資訊,主要用于自定義(擴充)的編譯器和調試器。一個classfile中隻能包含一項sourcefile attribute。

sourcedebugextension attribute

constant_pool中的索引,constant_utf8_info類型。指定attribute名稱(“sourcedebugextension”)。

debug_extension[attribute_length]

utf-8格式的字元串記錄擴充調試資訊,不以0結尾。

2.10.5     synthetic attribute

2.10.6     signature attribute

2.10.7     deprecated attribute

2.10.8     runtimevisibleannotations attribute

2.10.9     runtimeinvisibleannotations attribute