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