1. 程式人生 > >《深入理解Java虛擬機》讀書筆記五

《深入理解Java虛擬機》讀書筆記五

ss命令 出棧pop 管程 由於 表結構 兩個 pan 檢測 field

第六章 類文件結構

技術分享圖片

1、無關性的基石

  • 各種不同平臺的虛擬機與所有平臺都統一使用程序存儲格式——字節碼是構成平臺無關的基石。
  • 實現語言無關性的基礎仍然是虛擬機和字節碼存儲格式,Java虛擬機不和包括Java在內的任何語言綁定只能與class文件這種特定的二進制文件格式所關聯。
  • class文件包含了Java虛擬機指令集和符號表以及若幹其他輔助信息。

2、class文件結構

概述:

  • class文件是一組以八位字節為基礎的二進制流,各個數據項目嚴格按照順序緊湊的排列在class文件中。
  • class文件格式采用一種類似於C語言結構的偽數據結構來存儲數據,這種偽數據結構包含兩種數據類型無符號和表。
  • 無符號數屬於基本數據類型,從u1、u2、u4、u8來分別表示一個字節、兩個字節、四個字節、八個字節的無符號數。無符號數可以用來描述數字、索引、引用7數量值或者按照utf-8編碼構成字符串值。
  • 表是由多個無符號或者其他表作為數據項構成的復合數據類型。所有的表都習慣性地以“_info”結尾。表示描述有層次關系的復合結構的數據,整個class文件本質就是一張表。技術分享圖片

魔數:

  • 每個class文件的頭四位為魔數,作用是確定這個文件是否是一個能被虛擬機引用接受的class文件,class文件的魔數值是0xCAFEBABE。

class文件的版本:

  • 緊接著魔數的四個字節存儲的是class文件的版本號,第5和第6個字節是次版本號,第7和第8個是主版本號。

常量池:

  • 緊接著主版本號的是常量池入口,常量池可以理解為class文件中的資源倉庫,它是class文件結構中與其他項目關聯的最多的數據類型,也是占有class文件空間最大的數據項目之一,同時它是class文件第一個出現的表類型數據。
  • 由於常量池的常量數值不固定,所以在常量池的入口需要放置一項u2類型的數據代表常量池容量計數值,計數是從一開始的。
  • 常量池主要存放兩大常量,字面量和符號引用,字面量比較接近於Java語言層面的常量概念,如文字字符串,聲明為final的常量池等。
  • 符號引用包括類和接口的全限定名,字段的名稱和描述符,方法的名稱和描述符。
  • 常量池中每一項常量都是一個表,根據標誌位來確定項目類型。
    package
    com.ecut.clazz; public class TestClass { private int m; public int inc() { return m + 1; } }

    字節碼文件對應的16進制如下圖:技術分享圖片

    常量容量計數值為22則代表有21個常量,第一個常量的標誌位是0x0A,根據下表可知對應的項目類型是CONSTANT_Methodref_info,此類型代表類中方法的符號引用,這個項目類型對應的結構有兩個index,第一個index為0x0004為即十進制4,第二個index為0x0012即十進制18。第二個常量是以此類推,這個項目類型為CONSTANT_Fieldref_info,第一個index為0x0003即十進制3,第二個index為0x0013即十進制19。技術分享圖片
  • 剩下的常量可以借助class文件字節碼的工具javap來輸出TestClass.class文件字節碼內容。采用javap -verbose TestClass.class命令。技術分享圖片

訪問標誌:

  • 在常量池結束之後,緊接著的兩個字節代表訪問標誌,這個標誌用於標識一些類或者接口層次的訪問信息,包括是類還是接口,是否為public類型,是否為abstract。具體的標誌位以及標誌的含義如下表:技術分享圖片
  • access_flag中一共有16個標誌位可以使用,當前只定義了其中8個,沒有使用到的標誌位要求一律為0。技術分享圖片
  • TestClass被public修飾並且使用了jdk1.2之後的編譯器進行了編譯,因此它的access_flag標誌值應該為100001=0x21。

類索引、父類索引、接口索引:

  • 類索引用於確定表達這個類的全限定名,父類索引用於確定這個類的父類的全限定名,接口索引集合就用於描述這個類實現了那些接口,這些接口按implements語句從左到右排列在接口縮影集合中。

字段表集合:

  • 用於描述接口或類中聲明的變量。字段包括類級變量以及實例級變量,但不包括在方法內部聲明的局部變量。
  • 字段集合不會列出從超類中或者父類接口中繼承而來的字段,但有可能列出原本沒有的字段,如在內部類中為了保持外部類的訪問性會加入外部類的實例字段。
  • 字段包含信息:字段的作用域(public、private、protected),是實例變量還是類變量(static修飾符),可變性(final)、並發性(volatile修飾符,是否強制從主內存讀寫)、可否被序列化(transient修飾符),字段數據類型(基本類型、對象、數組),字段名稱。
  • 字段修飾符放在access_flag項目中,它包含兩項name_index和descript_index,他們都是對常量池的引用,分別代表字段的簡單名稱和字段的描述符。
  • 字段表結構如下圖所示:技術分享圖片
  • 結合之前的常量池中的常量可知類索引為 com/ecut/clazz/TestClass,父類索引為 java/lang/Object。TestClass包含一個被private修飾的int 類型的m。 技術分享圖片

方法表集合:

  • 方法表集合包括訪問標誌、名稱索引、描述符索引、屬性集合。如果父類方法在子類方法中沒有被重寫,方法表集合中不會有來自父類的方法信息。
  • 方法表結構如下圖:技術分享圖片

屬性表集合:

  • 在class文件中,字段表方法表都可以攜帶自己的屬性表集合,以用於描述某些場景專有的信息。
  • 屬性集合的結構如下圖:技術分享圖片
  • 結合常量池對文件進行分析可得,方法容量為2包含了兩個方法,第一個方法時public修飾void init,該方法包含了一個屬性code,code操作數棧最大值為1.第二個方法時public修飾的int inc()該方法也包含了一個屬性code。

技術分享圖片

  • Exception屬性列舉出方法中可能拋出的異常,也就是方法描述時在throws關鍵字後面列出的異常。
  • LineNumberTable屬性用於描述Java源碼行號和字節碼行號之間的對應關系。
  • LocalVariableTable屬性用來描述棧幀中局部變量與Java源碼中定義的變量之間的關系。
  • SourceFile屬性用來記錄生成這個class源碼文件名稱。

3、字節碼指令

概述:

  • Java虛擬機的指令由一個字節長度的,代表著某中特定操作含義的數字(稱為操作碼)以及跟隨其後的零至多個代表此操作所需參數(稱為操作數)而構成。
  • Java虛擬機采用面向操作數棧的架構所以大多數指令都不包含操作數只有一個操作碼。
  • 在Java虛擬機的指令集中大多數指令都包含了其操作鎖對應的數據類型信息。

加載和存儲指令:

  • 加載存儲指令用來將數據在棧幀中的局部變量和操作數棧之間來回傳輸。
  • 將一個局部變量加載到操作數棧iload。
  • 將一個數值從操作數棧中存儲到局部變量表istore。
  • 將一個常量加載到操作數棧bipush。
  • 擴充局部變量表的訪問索引的指令wide。

運算或算法指令:

  • 運算或算法指令用於對兩個操作數棧上的值進行某中特定的運算,並把結果重新存入操作數棧的棧頂。

類型轉換指令:

  • 類型轉換指令可以將兩種不同的數值類型進行相互轉換,這種轉換操作一般用於實現用戶代碼中的顯示類型轉換操作。
  • int——》long——》float——》double。

對象創建和訪問指令:

  • 雖然類實例和數組都是對象但是使用不同的指令來完成創建。
  • 創建類實例的指令 new。
  • 創建數組的指令 newarray。
  • 訪問類字段和實例字段 putfield 、getfield、getstatic。

操作數棧管理指令:

  • 將操作數棧的棧頂一個元素出棧pop。
  • 將棧頂兩個數值交換swap。

控制轉移指令:

  • 在有條件或者無條件的修改PC寄存器的值。
  • 條件分支ifea、iflt。
  • 復合條件分支lookupswich。
  • 無條件goto 。

方法調用和返回指令:

  • 方法調用指令和返回值無關,而方法返回指令是根據返回值類型來區分的。
  • invokevirtual用於調用對象的實例方法。
  • invokestatic用於調用類方法。

異常處理指令:

  • 在Java程序中顯示拋出異常的操作都有athrow指令來完成。
  • Java虛擬規範還規定許多運行時異常會在其他指令檢測到異常時自動拋出。

同步指令:

  • Java虛擬機可以支持方法級的同步和方法內部一段指令序列的同步,這兩種同步結構都是使用管程(Monitor)來支持的。

推薦博客鏈接:

https://blog.csdn.net/u010349169/column/info/jvm-principle

轉載請於明顯處標明出處:

https://www.cnblogs.com/AmyZheng/p/10537013.html

《深入理解Java虛擬機》讀書筆記五