虛擬機(jī)類文件結(jié)構(gòu)和加載機(jī)制

類文件結(jié)構(gòu)

虛擬機(jī)在對編譯代碼的時候會產(chǎn)生字節(jié)碼的文件,也就是class文件,這個字節(jié)碼文件的產(chǎn)生是java虛擬機(jī)實(shí)戰(zhàn)跨平臺語言操作的重要原因。

首先,這個class文件是一組由8個字節(jié)為基礎(chǔ)單位的二進(jìn)制流。它里面依次包括魔數(shù)和class文件版本、常量池、訪問標(biāo)志、類索引、父類索引與接口索引集合、字段表集合、方法表集合、屬性表集合

重點(diǎn)理解常量池和字段表

常量池:class文件的資源倉庫,為什么這么說呢?因為他里面存放著很多常量,包括字面量和符號引用,這些常量主要是:類和接口的全限定名、字段的名稱和描述符、方法的名稱和描述符。在之后的方法表和屬性表都會根據(jù)符號引用找到對應(yīng)的字面值

舉個例子,你在字段表中知道了該字段的作用域、字段名稱,它是通過標(biāo)志位來描述的,然后你通過這個標(biāo)志位去引用常量池中對應(yīng)的常量

常量池的每一個常量都是一個表

字段表與方法表以及索引集合、屬性表集合都是類似的,都是一些固定的指標(biāo)位分別來描述字段、方法、索引、屬性,再或者就是各自特定的信息(通過標(biāo)志位的引用找到常量池方法)



類加載機(jī)制

虛擬機(jī)在運(yùn)行程序的時候,需要將之前編譯好的class文件加載到內(nèi)存,而這個class文件包括了描述類的所有數(shù)據(jù),所以虛擬機(jī)之后還會對這些數(shù)據(jù)進(jìn)行處理

總的來說,虛擬機(jī)加載機(jī)制為:加載class文件、對數(shù)據(jù)進(jìn)行校驗、轉(zhuǎn)換解析、然后初始化,最終形成java類型

虛擬機(jī)要進(jìn)行加載是需要特定的時機(jī)的,也就是說需要特定的一些指令。比如在遇到new 、getstatic等指令就會進(jìn)行加載;當(dāng)對類進(jìn)行反射調(diào)用,若類沒有初始化,需要進(jìn)行加載使其初始化;初始化子類時,父類沒初始化,會先初始化父類;執(zhí)行主類(main)時會初始化;jdk1.7動態(tài)語言,對方法句柄解析結(jié)果之前要先初始化。之上的叫做類的主動引用

類加載的過程

加載:

1、獲取該類二進(jìn)制字節(jié)流(找到該類對應(yīng)的class文件)

2、把字節(jié)流的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運(yùn)行時的數(shù)據(jù)結(jié)構(gòu)

3、在內(nèi)存中生成這個類的java.lang.class對象

驗證:

驗證該class文件能被虛擬機(jī)識別讀?。ㄎ也孪霑止?jié)碼文件中的魔數(shù)有關(guān)),并不會危害虛擬機(jī)

準(zhǔn)備:

類變量(static變量)分配內(nèi)存

解析:

將常量池中的符號引用變?yōu)橹苯右?/p>

初始化:

執(zhí)行類構(gòu)造器方法



雙親委派模型


雙親委派模型示意圖


類加載在加載類的時候,一開始并不是自己加載,而是讓這個類的父類加載器去加載,以此類推,就能確保每個層次的類加載器都是由頂層啟動類加載器完成的時候除非父類加載器無法完成子類的加載

雙親委派模型確保了每個相同的類加載出來的類屬于同一個類,因為不同的類加載器會導(dǎo)致多個object實(shí)例對象為不同的Object對象,無法保證java體系最基礎(chǔ)的繼承等行為。所以雙親委派模型保證了java程序運(yùn)作的穩(wěn)定性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容