Java-字節碼文件深入解析的學習

JAVA字節碼整體結構

class文件結構中常量池中11種數據類型結構表

 

Access_Flag訪問標誌

 

字段表集合

fields_count:u2

 

方法表

methods_count:u2

 

方法的屬性結構

方法中的每一個屬性都是一個attribute_info:

1.使用javap -verbose分析一個字節碼文件時,將會分析該字節碼的魔數、版本號、常量池、類信息、類的構造方法、類中的方法信息、類變量與成員變量信息。

2.所有的.class文件的前四個字節都是魔數,魔數值爲固定值0xCOFEBABE。

3.魔數之後的四個字節爲版本信息,前兩個字節爲minor version(次版本號)後兩個字節爲major version(主版本號)

比如00 00 00 34換算爲十進制即爲0爲次版本號,3*16+4=52爲主版本號(52對應爲jdk8、51位jdk7.。。,),所以版本號即爲

1.8.0。

4.常量池(constant pool):緊接着主版本字節碼之後便是常量池入口,一個類中定義的很多信息都是又由常量池來維護和描述的,可以將常量池看作爲Class文件的資源庫,比如Java中的方法和變量信息,都是存儲在常量池中的,常量池中主要存儲兩類常量:字面量和符號引用。字面量如文本字符串,Java中聲明爲final類型的常量等,而符號引用如類和接口的全侷限定名,字段的名稱和描述符,方法的名稱和描述符。、

5.常量池總體結構:Java類對應的常量池主要由常量池數量和常量池數組(常量表)組成,常量池數量緊跟在主版本後面,佔據兩個字節;常量池數組則跟在常量池數量後面,常量池數組與一般的數組不同的是,常量池數組中不同元素的類型、結構都是不同的,長度當然也就不同,但是每一種元素的第一個數據都是一個u1類型,該類型是個標誌位,佔據一個字節,JVM在解析的時候會根據ul的類型去獲取元素的具體類型。注意:常量池數組中元素的個數 = 常量池數 - 1(其中0暫時不使用)。目的是在於某些常量池索引值的數據在特定的情況下需要表達【不引用任何一個常量池】的含義;根本原因在於索引爲0也是一個常量(保留常量),只不過它不位於常量表中,這個常量就對應null值;所以常量池的索引是從1開始而不是0。

6.在JVM規範中,每個變量\字段都有描述信息,描述信息主要的作用是描述字段的數據類型、方法的參數列表(包括數量、類型與順序)與返回值,無返回值和基本數據類型都有一個大寫字母表示,對象類型則是由L加上類的全限定名錶示,爲了壓縮體積基本數據類型都由一個大寫字母表示:int-I、char-C等,對象類型例:String類型對象爲Ljava/lang/String;

7.對於數組類型來說每一個維度使用前置的[來表示,int[]爲[I

8.用描述符描述方法時,先按照參數列表,將參數列表按照順序放到()中然後返回值如:String getName(int age,String card)表示爲(I,Ljava/lang/String)Ljava/lang/String

 

說明:

對於Java類中的每一個實例方法(非static方法),其在編譯後所生成的字節碼當中,方法參數的數量總是會比源代碼中方法參數多一個(this),它位於方法的第一個參數位置處;這樣我們就可以在方法中用this去訪問當前對象的屬性和其他方法。

這個操作是在編譯期間完成,即由javac在編譯的時候將對this的訪問轉化爲對一個普通方法的參數訪問;接下來在運行期間,由JVM調用方法時傳入該this參數,所以在實例方法中至少存在一個變量this指向當前的對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章