任何Java程序都要通過jvm虛擬機的處理生成class文件,而後而後虛擬機去解析class文件,下面咱們來介紹一下class文件的結構。java
Class文件格式採用的是相似於C語言的結構體的僞結構來存儲數據,這種僞結構只有兩種數據類型:無符號數和表;jvm
無符號數屬於基本的數據類型,以u1,u2,u3,u4,u8來表明1個字節、2個字節、4個字節、8個字節的無符號數,無符號數能夠用來描述數字、索引引用、數量值或者按照UTF-8編碼構成字符串值;工具
表是由多個無符號數或者是其餘表做爲數據項構成的複合數據類型,全部表都習慣以「_info」結尾。整個Class文件本質上就是一張表。編碼
Class文件不像XML文件那樣,因爲沒有任何的分隔符號,因此對於順序和數量,甚至於數據存儲的字節序這樣的細節,都是被嚴格限定的,哪一個字節表明什麼順序,長度是多少,都是不容許改變的。spa
每一個Class文件的頭4個字節都稱爲魔數,它的惟一做用就是判斷該文件是不是一個能被虛擬機接收的Class文件。緊接着魔數的4個字節存儲的是Class文件的版本號:第5和第6個字節存儲的是次版本號(Minor Version),第7和第8個字節存儲的是主版本號(Major Version),Java版本號是從45開始的。翻譯
下面分析一個簡單的Java程序對應的Class文件code
源文件
索引
class Test0 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("123"); } }
對應的Class文件接口
這裏的第八個字節值對應的十進制就是50,該版本號說明這個文件是能夠被JDK1.6或者以上版本虛擬機執行的Class文件。內存
緊接着主次版本號以後的是常量池入口,常量池能夠理解爲Class文件中的資源倉庫,因爲常量池中的常量數量不固定的,因此統一在和常量池的入口處須要存放一個u2(兩個字節)類型的數據,表明常量池容量計數值,與Java中語言習慣不同的是,這個計數是從1開始的而不是從0開始,Class文件中只有常量池的容量計數是從1開始的,對於其餘的集合類型,包括接口索引集合,字段表集合,方法表集合等的容量計數都是從0開始的,圖中0x001D表示的十進制數29表示常量池中有28項常量。字節碼的轉化按照十六進制ASCII標準
常量池中主要存放兩大類常量:字面量和符號引用,字面量比較接近Java語言層次的常量概念,如文本字符串,申明爲final的常量值等,而符號引用則屬於編譯原理方面的概念,包括下面三類常量:類和接口的全限定名,字段的名稱和描述符,方法的名稱和描述符。 當虛擬機運行時,就會從和常量池中獲取對應的符號引用,再在類建立或者運行時解析,翻譯到具體的內存地址之中。(常量池中的每一項常量都是一個表,JDK1.7中又額外增長了3種表結構數據,擁有14種表結構數據)。
如表1-1是常量池的項目類型
能夠看出,示例Class中第一項常量,它的標誌位是0x0A,查表1-1可知這個常量屬於CONSTANT_Methodref_info類型,此類型的常量表明類中方法的符號引用。
之因此說常量池是最煩瑣的數據,是由於這14種常量類型各自擁有本身的結構。
本例中一共有28個常量,其他的27個常量咱們能夠交由Oracle提供的專門用於分析Class文件字節碼的工具:Javap;效果如圖1-1
圖1-1 使用Javap命令輸出常量表
未完待續。。。