Java虚拟机:class类文件结构
一、平臺無關性:
????????Java的無關性的實現,是由Java源代碼編譯后生成的字節碼class文件和Java虛擬機實現的。無關性包括:平臺無關性以及語言無關性。
????(1)平臺無關性,是指java代碼可以運行在不同操作系統的虛擬機上面,因為不同的操作系統都有各自的Java虛擬機,從而實現程序的“一次編寫,到處運行”。
????(2)語言無關性是指Java虛擬機能運行除Java以外的代碼,JVM執行的是class文件,也就是JVM只認識class文件,它并不關心Class文件的來源是什么語言,只要它符合一定的結構,就可以在Java中運行。
?
二、類文件結構:
class文件是Java虛擬機執行引擎的數據入口,是一組以8位字節為基礎單位的二進制流,存儲的內容幾乎都是程序運行的必要數據。
class文件的數據存儲結構中只有兩種數據類型:無符號數和表。class文件中的數據項,都被嚴格限定的,每個字節代表的含義,長度,先后順序等都不允許改變。
(1)無符號數屬于基本數據類型,以u1、u2、u4、u8來分別代表1、2、4、8個字節的無符號數。
(2)表是由多個無符號數或其他表作為數據項構成的復合數據類型。
class類文件的結構:
????1.?魔數
????2.?文件版本信息
????3.?常量池
????4.?訪問標志
????5.?類索引、父類索引、接口索引集合
????6.?字段表集合
????7.?方法表集合
????8.?屬性表集合
1、魔數:
????????每個Class文件的頭4個字節稱為魔數(magic),它的唯一作用是判斷該文件是否為一個能被虛擬機接受的Class文件。它的值固定為0xCAFEBABE。
2、文件版本信息:
????????緊接著magic的4個字節存儲的是Class文件的次版本號和主版本號,高版本的JDK能向下兼容低版本的Class文件,但不能運行更高版本的Class文件,即使該版本沒有用到高版本JDK的特性。
3、常量池:
????????緊接著版本號之后的就是常量池入口,它是class文件中的資源倉庫。它是Class文件中與其他項目關聯最多的數據類型,也是占用Class文件空間最大的數據項目之一。常量池中主要存放兩大類常量:字面量和符號引用。
????????字面量比較接近于Java層面的常量概念,如文本字符串、被聲明為final的常量值等。
????????而符號引用總結起來則包括了下面三類常量:
?????????(1)類和接口的全限定名
?????????(2)字段的名稱和描述符
?????????(3)方法的名稱和描述符
4、訪問標志:
????????在常量池結束之后,緊接著的2個字節代表訪問標志(access_flag),這個標志用于識別一些類或接口層次的訪問信息,包括:這個Class是類還是接口,是否定義為public類型,abstract類型,如果是類的話,是否聲明為final,等。
5、類索引、父類索引、接口索引集合:
????????Class文件中由這三項數據來確定這個類的繼承關系。類索引、父類索引和接口索引集合都按照順序排列在訪問標志之后。類索引用于確定這個類的全限定名,父類索引用于確定這個類的父類的全限定名。接口索引集合就用來描述這個類實現了哪些接口。
6、字段表集合:
????????字段表(field_info)用于描述接口或類中聲明的變量。字段包括了類級變量或實例級變量,但不包括在方法內聲明的變量。可以包括的信息有:字段的作用域、是實例變量還是類變量、可變性、并發可見性、可否被序列化、字段數據類型、字段名稱。但是,字段的名字、數據類型、修飾符等都是無法固定的,只能引用常量池中的常量來描述。
????????字段表集合中不會列出從父類或接口中繼承而來的字段,但有可能列出原本Java代碼中不存在的字段。比如在內部類中為了保持對外部類的訪問性,會自動添加指向外部類實例的字段。
7、方法表集合:
????????方法表(method_info)的結構與字段表的結構相同。方法里的Java代碼,經過編譯器編譯成字節碼指令后,存放在方法屬性表集合中一個名為“Code”的屬性里。
????????與字段表集合相對應,如果父類方法在子類中沒有被覆寫,方法表集合中就不會出現來自父類的方法信息。但同樣,有可能會出現由編譯器自動添加的方法,最典型的便是類構造器“<clinit>”方法和實例構造器“<init>”方法。
????????重載一個方法需要有相同的簡單名稱和不同的特征簽名。JVM的特征簽名和Java的特征簽名有所不同:?
????????(1)Java特征簽名:方法參數在常量池中的字段符號引用的集合
????????(2)JVM特征簽名:方法參數+返回值
8、屬性表集合:
????????屬性表(attribute_info),在Class文件、字段表、方法表中都可以攜帶自己的屬性表集合,以用于描述某些場景專有的信息。
(1)Code屬性:
????????Java程序方法體中的代碼講過Javac編譯后,生成的字節碼指令便會存儲在Code屬性中,但并非所有的方法表都必須存在這個屬性,比如接口或抽象類中的方法就不存在Code屬性。
????????Code屬性是Class文件中最重要的一個屬性,如果把一個Java程序中的信息分為代碼和元數據兩部分,那么在整個Class文件里,Code屬性用于描述代碼,所有的其他數據項目都用于描述元數據。
(2)Exception屬性:
????????這里的Exception屬性的作用是列舉出方法中可能拋出的受查異常,也就是方法描述時在throws關鍵字后面列舉的異常。
(3)LineNumberTable屬性:
????????它用于描述Java源碼行號與字節碼行號之間的對應關系。
(4)LocalVariableTable屬性:
????????它用于描述棧幀中局部變量表中的變量與Java源碼中定義的變量之間的對應關系。
(5)SourceFile屬性:
????????它用于記錄生成這個Class文件的源碼文件名稱。
(6)ConstantValue屬性:
????????ConstantValue屬性的作用是通知虛擬機自動為靜態變量賦值,只有被static修飾的變量才可以使用這項屬性。
????????在Java中,對非static類型的變量(也就是實例變量)的賦值是在實例構造器<init>方法中進行的;而對于類變量(static變量),則有兩種方式可以選擇:在類構造其中賦值,或使用ConstantValue屬性賦值。
????????如果同時使用final和static修飾一個變量(即全局常量),并且這個變量的數據類型是基本類型或String的話,就生成ConstantValue屬性來進行初始化,如果該變量沒有被final修飾,或者并非基本類型及字符串,則選擇在<clinit>方法中進行初始化。
(7)InnerClasses屬性:
????????該屬性用于記錄內部類與宿主類之間的關聯。如果一個類中定義了內部類,那么編譯器將會為它及它所包含的內部類生成InnerClasses屬性。
(8)Deprecated屬性:
????????Deprecated該屬性用于表示某個類、字段和方法,已經被程序作者定為不再推薦使用,它可以通過在代碼中使用@Deprecated注釋進行設置。
(9)Synthetic屬性:
????????該屬性代表此字段或方法并不是Java源代碼直接生成的,而是由編譯器自行添加的,如this字段和實例構造器、類構造器等。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java虚拟机:class类文件结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux:常用命令大全
- 下一篇: Java虚拟机:JVM 主要组成部分与内