深入理解JAVA虛擬機學習筆記12——Class類文件的結構(1常量池)

前一篇文章已經對Class類文件匆匆一瞥,上一篇沒看的,建議先看一下上一篇,這一篇就看一下具體的細節。

我們先隨便創建一個類,代碼如下。

運行main方法,這個時候會生成一個class文件,我們用文本編輯器打開它。

由於class文件中是二進制流,直接打開會顯示一堆亂碼,爲了方便查看,我們以16進制編碼格式打開文件,需要藉助一下插件。

筆者用的是Nodepad++,在菜單欄中找到“插件”,依次選擇“Plugin Manager”——“Show Plugin Manager”,找到“HEX-Editor”,點擊“install”,安裝成功後重啓。

再次打開文件後,我們點擊功能按鈕中最後的那個“H”,這時,呈現在我們眼前的就是16進制的CLASS文件了,也就是說肉眼可見的2個字符,如“ca”,實際就是“1100 1010”,還記得上一篇說的嗎,8個bit代表一個字節。

雖然說,這個Class文件終於轉換成我們能認出來的字符了,但是這密密麻麻的字母數字都是啥啊?密集恐懼症都犯了!

彆着急,我們接下來就來一點一點的解析。

一、 0-3字節:字符“ca fe ba be”,固定的標識,代表這是一個java的class文件。

其實這個“魔數”,並不是只有class文件纔有。

讓我們用Nodepad++分別打開兩張不同的圖片,內容以16進制展現。

我們驚奇的發現,前三個字節居然都是“89 50 4e 47”,到底是巧合還是人性的泯滅?

哈哈,不開玩笑,其實很多課執行文件都包含“魔數”,將文件的頭四個字節用來標識文件屬於什麼格式,如下圖所屬(圖片來自維基百科)。

如果我想把標識設置成“iloveyou”是不是很炫酷,哦,16進制裏面沒有“i”啊。

二、 4-7字節:標識後緊接着的四個字節是Class文件的版本號(筆者理解爲:你用哪個java版本編譯的class文件)。這其中又分爲兩部分。

4,5字節:小版本號(Minor Version,書中叫次級版本號),“00 00”轉換成10進制就是“0”。

6,7字節:大版本號(Major Version,書中叫主版本號),“00 34”轉換成10進制就是“52”。

那麼,這兩塊組合到一起就是52.0。

而JAVA版本號從是45開始,JDK1.1之後,每個JDK大版本,JAVA版本號+1,52.0實際上就是JDK8.0了。

另外,一直都說JDK可以向下兼容,但不能向上兼容,也就是說,一旦虛擬機發現當前JDK版本低於class文件的版本,將不予執行。

前面是相對比較簡單的,接下來的可以能就一點小複雜了,不過也不用緊張,這個看完就沒了。

學習之前,我們在cmd執行命令:javap -v App,看一下App.class的反編譯信息,更有助於我們的理解。

三、8,9字節:看一下類型表,類型是U2,說明佔兩個字節,名稱爲“constant_pool_count”,字面意思理解就是“常量池個數”,“00 22”說明總數有34項,但是需要注意的是第0項是空出來了(當某一個常量不指向任何引用的時候,則指向第0項),實際常量只有33個(即圖中#1到#33)。

常量池中存兩大類常量:

字面量:文本字符串,final的常量值;就是圖中等於“=Utf8”的,如#7,#8等都是字面量。

符號引用:類和接口的全限定名(等於“Class”,如#5,#6);字段的名稱和描述符(Fieldref);方法的名稱和描述符(Methodref);

每一個常量都對應着下表中的一個類型。

四、知道了有多少個常量之後,就是具體的常量集合了,下面先看第一個。

a字節:“0a”轉換爲10進制就是10,查找上面的常量類型對應表,說明這個常量類型是“CONSTANT_Methodref_info”,我們再到下標中查詢對應的常量和結構,可以看到tag佔一個字節,值是10,其實就是a字節。只有確定了常量類型,才能確定下來接下來的字節含義。

b,c字節:根據“CONSTANT_Methodref_info”的結構,我們看到接着的index爲u2,佔兩個字節,指向聲明方法的類描述符的索引項,轉化爲十進制就是“06”,結合上面的反編譯信息,指向的其實就是#6,#6又指向#27,也是java/lang/Object。

d,e字節:也是一個index,轉化後指向的是#20,又指向……最後的值爲"<init>":()V,就是所說的方法名稱描述符了。

看到這裏,可能有的朋友開始迷惑了,這表示的是什麼東西啊,代碼裏也沒有啊?

看官,還記得大明湖畔的……呃,不,java類實例構造器的init方法嗎!

看起來比較複雜,其實一步一步來,是不是很簡單,剩下的常量感興趣的親自動手試試吧!

喜歡文章或想一起學習的朋友可以關注我,給我點贊,我將會持續更新,有什麼疑問或文中有不當之處請給我留言,真誠地希望能與大家一起交流探討,學習進步。


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