一、什麼是java類別檔案
Java類別檔案是Java程式的二進位表示形式。每一個類別文件代表一個類別或者介面。不可能在一個類別文件中放入多個類別或介面。這樣就使得無論類別檔案是在哪一種平台上生成,都可以在任何主機上執行。
雖然類別檔案是Java體系結構的一部分,但他並不是與Java語言不可區分的。你可以將其他語言的程式編譯為類別文件,也可以將Java程式檔案編譯為其他二進位形式。
Java類別檔案是一個基於8-bit位元組的二進位流。資料區塊順序的、無分割符的、big-endian的形式儲存。
二、類別檔案的內容
Java的類別檔案中包含了所有Java虛擬機器所需的關於類別和介面的資訊。所有類別檔案中的資訊都以以下的四種基本類型的儲存:
Table 6-1. Class file "PRimitive types"
u1 a single unsigned byte
f signed bytes
u8 eight unsigned bytes
類別檔案中的主要部分以表6-2的順序儲存:
Table 6-2. Format of a ClassFile Table
類型& u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count-1
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
1、魔術編碼(magic)
每個Java類別檔案的開頭四個位元組都是魔術編碼(OxCAFEBABE)。透過魔術編碼可以很輕易地辨識類別文件。
2、副版本號和主版本號(minor_version and major_version)
剩下的四個位元組是副版本號和主要版本號。但Java技術在進化時,一些新的特性可能會加入到類別文件中。每一次類文件格式的變化,都會相應的改變版本號。虛 擬機透過版本號來辨識自己能夠處理的類別文件。 Java虛擬機往往只能處理一個給定的主版本號碼和其下的一些副版本號。虛擬機器必須拒絕那些不再處理範圍內的類別 檔案。
3、常數個數和常數池(constant_pool_count and constant_pool)
接下來的就是常數池,常數池中包含了哪些被類別或介面存取過的常數,例如:字串,常數(final variable values),類別名,方法名。常量池作為一個清單儲存。清單中常數的個數就是先前儲存的「constant_pool_count」。
許多常量池中的常數都引用了常量池中的其他常數,那些引用常數池常數的引用最終也會轉換為對常量池中常數的直接引用。雖然常數列表中的索引是從1開始的,但是常數個數還是包含了0,例如一個常數列表中有15個常數,那麼它的常數個數就為16。
每個常數開頭都會有一個標誌,以表示他的類型。當虛擬機器讀取這個標誌時,就會知道這個常數的具體類型了。表6-3列舉了這些標誌:
Table 6-3. Constant pool tags
Entry Type Tag Value Description
CONSTANT_Integer 3 An int literal value
CONSTANT_Float 4 A float literal value
4 A float literal value
4 A float literal value
5 A long literal value
CONSTANT_Double 6 A double literal value
CONSTANT_Class CONSTANT_String 8 A String literal value
CONSTANT_Fieldref 9 A symbolic lared in a class
CONSTANT_InterfaceMethodref 11 A symbolic reference to a method declared in an interface
a field or method
表6-3中的每一個標誌都會有一個對應的表格,用來描述這個標誌的所表示的一些具體訊息,這些對應的標誌都會以標誌名+_INFO來結尾。例如CONSTANT_CLASS標誌對應的就是CONSTANT_CLASS_INFO。
常數池在程式的動態連結中扮演了很重要的角色。除了上邊所說的各種常數值以外,常數池中包含了一下三種符號引用:類別和介面的全名,字段名和描述符,方法名 和描述符。一個欄位是一個類別或介面中的實例或類別變量,欄位描述符是欄位的類型。方法的描述符是方法和傳回值和參數的數量、順序和類型。在虛擬機器將這個 類別或介面連結到其他類別或介面時用到這些全名。因為類別文件不包含任何關於記憶體結構的信息,所以這個連結只能以符號引用的形式存在。虛擬機器在執行時將這些 符號參考轉換為實際的位址。具體的資訊請參閱第八章「The Linking Model」。
4、存取標誌(access_flags)
緊接在常數池後面的兩個位元組就是存取標誌,表示這個類別或介面的幾方面資訊,他有以下幾種值:
Table 6-4. Flag bits in the access_flags item of ClassFile tables
Flag Name Value Meaning if Set Set By
ACC_PUBLIC Set By
ACC_PUBLIC ACC_FINAL 0x0010 Class is 已知 0x0200 Type is an interface, not a class All interfaces, no classes
ACC_ABSTRACT 0x0400 Type is abstract All interfaces, some classes
所有沒有使用的訪問標誌,必須設定為0。
5、類別名稱(this_class)
接下來的兩個位元組保存了一個常數池的索引。這個常數池中的實體必須是CONSTANT_CLSS_INTO型的,他包含了標誌和名字索引。標誌就是 CONSTATN_CLASS,那個名字索引應該是保存了這個類別或是介面全名的CONSTANT_UTF8_INFO類型的索引。
6、父類別(super_class)
this_class之後的就是兩個位元組的super_class,他也是一個常數池的索引,其中保存了父類別的全名,處理this_class一樣。當父 類別是java.lang.Object時,super_class都應該是0。對於介面super_class都是0。
7、(interfaces_count and interfaces)
interfaces_count中保存了父介面的個數,interfaces中以陣列形式保存了一些常數池的索引。每一個索引都指向了一個 CONSTANT_CLASS_INFO的常數,其中保存了每一個父介面的全名。這個數組的順序就是父介面出現在implements、extends 語句中從左到右的順序。
8、(fields_count and fields)
欄位保存在一個field_info的清單中,fields_count是這個清單的長度。 Field_info清單中保存的只是類別或介面中的申明的變量,從父類別或父介面中繼續的欄位不保存在這裡。
每一個field_info表中的一個都描述了一個欄位的訊息,包括:欄位名,描述符,存取權限。假如一個欄位被申明為final,那麼這個欄位的資訊就會保存在field_info表中,也會保存在常數池中。
9、(methods_count and methods)
方法的資訊都保存在method_info表中,mehtods_count是表的長度。 Method_info表中只保存類別或介面中申明的方法,不保存從父類別或介面中繼續的方法。
Method_info 表中保存了方法名稱和描述符(傳回值和參數類型)。假如不是抽象方法,還會保存用於堆疊的大小(保存本地變數用的)、操作數堆疊的最大值、捕捉的異常列表、 方法的字節碼、可選的行號和本地變數表。假如方法拋出一些被檢查的異常,method_info還會包含一個被檢查異常的清單。
10、(attributes_count and attributes)
類別檔案中最後的是屬性個數和atribute_info清單。 Atribute_info表中保存了一些指向常數池中constant_utf8_info的索引,其中保存了屬性的名字。 Java虛擬機器規格中定義了兩種類型的屬性:原始碼和內部類別。
以上就是Java入門:java類別檔案詳解的內容,更多相關文章請關注PHP中文網(www.php.cn)!