雖然介紹完了常量池, 但是class文件中位于常量池下面的內容還有很多呢。 接下來, 我們就分析class文件中位于常量池下面的內容, 不用擔心, 只要把常量池搞明白了, 這些內容就會很容易理解。?
在開始進入正文之前, 在這里再次給出class文件的整體格式。 這個表格曾出現在?深入理解Java Class文件格式(一)?這篇文章中。 之所以把這個表格列在這里, 是想再次給讀者一個class文件的總體概覽。表格的內容如下:
class文件中的訪問標志信息
從上面的表格可以看出, 位于常量池下面的2個字節是access_flags 。?access_flags 描述的是當前類(或者接口)的訪問修飾符, 如public, private等, 此外, 這里面還存在一個標志位, 標志當前的額這個class描述的是類, 還是接口。access_flags 的信息比較簡單, 下面列出access_flags 中的各個標志位的信息。本來寫這個系列文章參考的是《深入java虛擬機》, 但是這本書比較老了, 關于java
5以后的新特性沒有進行解釋,這本書中指列出了5個標志值, 而的JVM規范是針對java 7 的, 其中加入了額外的三個標志位。 分別是ACC_SYNTHETIC, ACC_ANNOTATION 和 ACC_ENUM ?。
而ACC_SUPER這個標志位在java 1.2的時候加入到class文件中, 它為invokespecial這條指令增加了動態綁定的功能。 這里可能有幾個概念讀者不是很明白, 如靜態綁定, 動態綁定等, 這些概念會在以后的博客中詳細介紹。
還有一點需要說明, 既然access_flags 出現在class文件中的類的層面上, 那么它只能描述類型的修飾符, 而不能描述字段或方法的修飾符, 希望讀者不要將這里的access_flags 和后面要介紹的方法表和字段表中的訪問修飾符相混淆。
此外, 在Java 5 的中, 引入和注解和枚舉的新特性, 那么可以推測,??ACC_ANNOTATION 和 ACC_ENUM是在Java 5版本中加入的。 class文件雖然總體上保持前后一致性, 但他也不是一成不變的, 也會跟著Java版本的提升而有所改變, 但是總體來說, class文件格式還是相對穩定的, 變動的地方不是很多。?
class文件中的this_class
訪問標志access_flags 下面的兩個字節叫做this_class, 它是對當前類的描述。 它的兩個字節的數據是對常量池中的一個CONSTANT_Class_info數據項的一個索引。?CONSTANT_Class_info在上面的文章中已經介紹過了。?CONSTANT_Class_info中有一個字段叫做name_index, 指向一個CONSTANT_Utf8_info , 在這個CONSTANT_Utf8_info 中存放著當前類的全限定名。?
如果當前類為Person:
super_class緊跟在this_class之后。 它和this_class一樣是一個指向常量池數據項的索引。 它指向一個CONSTANT_Class_info, 這個CONSTANT_Class_info數據項描述的是當前類的超類的信息。CONSTANT_Class_info中的name_index指向常量池中的一個CONSTANT_Utf8_info,CONSTANT_Utf8_info 中存放的是當前類的超類的全限定名。 如果沒有顯式的繼承一個,也就是說如果當前類是直接繼承Object的, 那么super_class值為0 。 我們在前面的文章中提到過, 如果一個索引值為0, 那么就說明這個索引不引用任何常量池中的數據項,
因為常量池中的數據項是從1開始的。 也就是說, 如果一個類的class文件中的super_class為0 , 那么就代表該類直接繼承Object類。?
下面以代碼來說明:
緊接著super_class的是interfaces_count, 表示當前類所實現的接口的數量或者當前接口所繼承的超接口的數量。 注意, 只有當前類直接實現的接口才會被統計, 如果當前類繼承了另一個類, 而另一個類又實現了一個接口, 那么這個接口不會統計在當前類的interfaces_count中。
在interfaces_count后面是interfaces, 他可以看做是一個數組, 其中的每個數組項是一個索引, 指向常量池中的一個CONSTANT_Class_info, 這個CONSTANT_Class_info又會引用常量池中的一個CONSTANT_Utf8_info, 這個CONSTANT_Utf8_info 中存放著有當前類型直接實現或繼承的接口的全限定名。 當前類型實現或繼承了幾個接口, 在interfaces數組中就會有幾個數項與之相對應。?
下面看代碼示例:
下面是示意圖(其中虛線范圍內表示常量池的區域):
在本篇文章中, 繼續講解了class文件中常量池以下的部分。 主要講解了三個部分, 分別是this_class , super_class , interfaces_count和interfaces 。 這三個數據項分別描述了當前類(就是當前class文件所在的類), 當前類所繼承的超類, 和當前類所實現的接口(如果當前class文件代表的是一個接口, 那么?interfaces_count和interfaces描述的是當前接口所繼承的超接口)。
這幾個數據項都持有指向常量池的索引。 真實的信息都是存放在常量池中的, 只不過常量池中的這些信息會被this_class , super_class , interfaces_count和interfaces 引用。?
通過本篇文章我們可以知道源文件中的當前類, 當前類的超類以及當前類的超接口在class文件中是如何被描述的。 在下一篇文章中, 將會講解源文件中的定義的字段, 聲明的方法在class文件中是如何描述的。想要了解更多的java學習技術那就加入我們吧!