【JVM虛擬機】(6)---深刻理解Class中訪問標誌、類索引、父類索引、接口索引

<center> JVM(6)訪問標誌,類索引</center>

上一篇博客講【JVM虛擬機】(5)---深刻理解JVM-Class中常量池javascript

咱們知道一個class文件正常能夠分爲7個部分:html

  • 魔數與class文件版本
  • 常量池
  • 訪問標誌
  • 類索引、父類索引、接口索引
  • 字段表集合
  • 方法表集合
  • 屬性表集合

那麼這篇博客主要講有關 訪問標誌類索引、父類索引、接口索引 相關的理解和代碼示例。java

先通俗的說下這兩個的做用:測試

訪問標誌: 告知該類是一個什麼類型的類,是普通類?仍是接口?仍是枚舉?或者其它類,是用什麼修飾符修飾該類的。spa

類索引、父類索引、接口索引: 告知該類全限名的常量池地址,有繼承的話父類全限名的常量池地址,實現接口的話接口全限名的常量池地址(接口能夠多個)。code

<font color=#FFD700> 1、概述</font>

先對上篇博客作個補充:上篇博客雖說了常量池但對class總體文件結構並無說清楚,其實一個class文件即htm

.class 文件本質上就是一張,由下表所示的數據項構成。blog

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135031721-1835822396.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="612">繼承

上圖也就是一開始所講的7個部分組成。索引

<br>

<font color=#FFD700> 2、訪問標誌</font>

有關訪問標誌找了不少資料,也看了《深刻了解java虛擬機》書中第六章給的有關訪問標誌的信息,網上幾乎講訪問標誌都是下面這張圖,而後寫個pulic class 類 一測試,果真是0021 表明 ACC_PUBLIC+ACC_SUPER 這樣一看是沒毛病。可是都沒有再寫一個接口來驗證的,若是本身寫個接口就會發現下面我圈紅的地方說,JDK1.2後該處必須爲真 是不對的。先看圖。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135129522-1831389208.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="700" height="412">

一、訪問標誌轉爲16進制解釋

思考:就比如爲何ACC_PUBLIC是00 01?如何產生的呢。

訪問標誌實際上就是一系列組合,由於有16位因此共有16個標誌可使用,可是目前就定義了8個,剩下的估計是給jdk9和10......預留的吧。這8個如圖所示。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135139548-792467058.png" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="426">

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135148442-1272202826.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="420">

講完理論,接下來咱們進行代碼測試,爲了校驗更佳準確我寫個普通類和接口分別測試:

二、public class修飾類

public class XiaoXiao {
  
}

在同一目錄生成成class文件

javac XiaoXiao.java

在看反編譯class文件

javap -v XiaoXiao.class

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135200951-1944917775.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="274">

咱們發現這裏flags爲: ACC_PUBLIC, ACC_SUPER,那這麼推算那麼十六進制應該是0021。

那咱們再來查看XiaoXiao.class的十六進制數據

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135210605-118543476.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="370">

完美吻合。

三、接口校驗

public interface DaDa {

}

一樣先生成class文件在反編譯class文件

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135219909-386750991.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="247">

看圖咱們能夠發現flags值爲:ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT ,這個也很好理解接口自己就是抽象類。那麼加起來就是0601。但這裏和上圖有點不符的地方就是圖中說ACC_SUPER只要是JDK1.2必須爲真,而這裏明顯不爲真,因此有關這點並不許確。

那咱們再將class文件轉位16進制驗證。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135232383-1170041644.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="218">

這麼一來驗證也是經過的。

有關ACC_SUPER不許確的問題,應該是ACC_SUPER不會是在JDK1.2之後必須爲真,應該以下描述:

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135241834-913919387.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="410">

<br>

<font color=#FFD700> 3、類索引、父類索引、接口索引 </font>

一、概念

在 .class 文件中由這三項數據來肯定這個的繼承關係。

一、類索引:u2 數據類型,用於肯定這個類的全限定名。

二、父類索引:u2 數據類型,用於肯定這個類的父類的全限定名。

三、接口索引:u2 數據類型的集合,用於描述類實現了哪些接口,這些被實現的接口將按照 implements 語句後的順序從左至右排列在接口索引集合中。

接口索引集合分爲兩部分,第一部分表示接口計數器(interfaces_count),是一個 u2 類型的數據,第二部分是接口索引表表示接口信息,緊跟在接口計數器以後。

若一個類實現的接口爲 0,則接口計數器的值爲 0,接口索引表不佔用任何字節。

一樣這裏測試寫兩個測試類來測試。

一、普通類測試

public class XiaoXiao {
  
}

一樣生成class文件,而後查看16進制數據

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135252392-556980563.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="425">

咱們看到該類的類索引在常量池0002位置 ,父類索引在常量池0003位置,接口爲0000表明該類沒有實現任何接口。

而後咱們在反編譯XiaoXiao.class文件,方便咱們查找常量池。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135305029-1927119339.jpg" style="border: 2px dashed rgb(204, 200, 200);" width="600" height="273">

真的是一目瞭然,常量池0002就是當前類,0003父類爲默認繼承了老祖宗Object。

完美!

二、實現接口測試

爲了更加深入理解,這裏再寫一個類實現兩個接口的類,在來查看。

//接口
public interface DaDa { 
}
//接口
public interface LaLa {
}
//類實現上面兩個接口
public class XiaoXiao implements  DaDa ,LaLa{
}

說明:這裏不能經過 javac XiaoXiao.java生成XiaoXiao.class文件了,由於會報錯。我分析緣由是由於你手動編譯是沒法找到DaDa ,LaLa編譯信息。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135321017-796665369.jpg" style="border: 2px dashed rgb(204, 200, 200);" width="600" height="385">

因此咱們能夠把整個項目啓動後,到target目錄下去找該class文件就能夠。

在打開16進制文件。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135331220-1772694961.jpg" style="border: 2px dashed rgb(204, 200, 200);" width="600" height="260">

咱們看到該類的類索引在常量池0002位置 ,父類索引在常量池0003位。接口爲0002表明該類實現了兩個接口,一個接口在常量池位置004,一個在常量池位置0005。

在看反編譯後的class文件。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190409135343028-161944163.jpg" style="border: 2px dashed rgb(204, 200, 200);" width="600" height="286">

驗證成功!

##<font color=#FFD700>參考 </font>

一、深刻了解java虛擬機第2版第六章

二、深刻理解JVM-Class文件結構和類加載

<br> <br> ``` 只要本身變優秀了,其餘的事情纔會跟着好起來(少將4) ```

相關文章
相關標籤/搜索