JVM—類加載過程學(xué)習(xí)

1 類加載過程圖解

類加載過程

??系統(tǒng)加載Class類型的文件主要是:加載->連接->初始化,其中連接分為:驗證->準(zhǔn)備->解析;其實,整個生命周期是7步,類從被加載到虛擬機(jī)內(nèi)存中開始,到卸載出內(nèi)存為止,分為:加載->驗證->準(zhǔn)備->解析->初始化->使用->卸載。

2 加載

??加載分為三步:
1)通過全類名獲取定義此類的二進(jìn)制字節(jié)流;
2)將字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu);
3)在Java堆中生成一個代表該類的java.lang.Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口;
??其中,獲取字節(jié)流的方式:從Zip包中獲?。╦ar,ear,war等);從網(wǎng)絡(luò)中獲取(Applet);運行時計算生成(動態(tài)代理技術(shù));其他文件(JSP文件);數(shù)據(jù)庫讀取。

3 驗證

??1.作用:驗證是連接階段的第一步,目的是確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會危害虛擬機(jī)自身的安全。如果驗證到輸入的字節(jié)流不符合Class文件格式的約束,jvm就拋出java.lang.VerfyError異?;蚱渥宇惍惓?。
??2.驗證階段大致經(jīng)歷4個階段的檢驗動作:文件格式驗證、元數(shù)據(jù)驗證、字節(jié)碼驗證、符號引用驗證。第一個基于二進(jìn)制字節(jié)流;后面三個是基于方法區(qū)的存儲結(jié)構(gòu)。
(1) 文件格式驗證
??作用:驗證字節(jié)流是否符合Class文件格式的規(guī)范,并且能被當(dāng)前版本的虛擬機(jī)處理。
??如:是否以魔數(shù)0xCAFEBABE開頭;主次版本號是否在當(dāng)前VM處理范圍之內(nèi);
??常量池的常量中是否有不被支持的常量類型(tag標(biāo)志);
??目的:保證輸入的字節(jié)流能正確地解析并存儲于方法區(qū)之內(nèi),格式上符合一個Java類型的要求。
(2) 元數(shù)據(jù)驗證
??作用:對字節(jié)碼描述的信息進(jìn)行語義分析,保證其描述的信息符合Java語言規(guī)范的要求。
??如:這個類是否有父類(處Object外,所有類都有父類);
??這個類的父類是否繼承了不允許被繼承的類(final修飾的類);
??如果這個類不是抽象類,是否實現(xiàn)了父類或接口的所有要實現(xiàn)的方法;
??類中字段、方法是否與父類產(chǎn)生矛盾(覆蓋父類final字段,方法重載不符合規(guī)則);
??類中是否有父類、是否合法的繼承類、是否實現(xiàn)了父類或接口的方法、字段和方法是否與父類產(chǎn)生矛盾
??目的:保證對類的元數(shù)據(jù)信息進(jìn)行語義校驗,保證不存在不符合Java語言規(guī)范的元數(shù)據(jù)信息。
(3) 字節(jié)碼驗證
??作用:對類的方法體進(jìn)行校驗分析,保證被校驗類的方法在運行時不會做出危害VM安全的事件;
??如:保證任意時刻操作數(shù)棧的數(shù)據(jù)類型與指令代碼序列都能配合工作;
??保證跳轉(zhuǎn)指令不會跳轉(zhuǎn)到方法體以外的字節(jié)碼指令上;
??保證方法體中的類型轉(zhuǎn)換是有效的;
??方法體:類型轉(zhuǎn)換是否有效、操作數(shù)棧和指令代碼是否匹配工作、跳轉(zhuǎn)指令是否跳轉(zhuǎn)到正確位置
??目的:通過數(shù)據(jù)流和控制流分析,確定程序語義是合法、符合邏輯的
(4) 符號引用驗證
??作用:發(fā)生在VM將符號引用轉(zhuǎn)化為直接引用的時候,轉(zhuǎn)化動作在連接的第三階段——解析階段中發(fā)生。是對類自身以外的信息進(jìn)行匹配性校驗。
??如:符號引用中通過字符串描述的全限定名是否能找到對應(yīng)的類;
??在指定類中是否存在符合方法的字段描述符以及簡單名稱所描述的方法和字段;
??符號引用中的類、字段、方法的訪問性是否能被當(dāng)前類訪問。
??目的:確保解析動作能正常執(zhí)行,如果無法通過符號引用驗證,拋java.langIncompatibleClassChangeErrot異常的子類,如java.langIllegalAccessError、java.lang.NoSuchFieldError和java.lang.NoSuchMethodError等。

4 準(zhǔn)備

作用:
是正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配。
注意:
1)該階段進(jìn)行內(nèi)存分配僅包括類變量(static修飾的),不包括實例變量,實例變量是在對象實例化隨著對象一起分配在Java堆中。
2)初始值是數(shù)據(jù)類型的零值:例如public static int value = 123; 準(zhǔn)備階段:value=0; 初始化階段:value=123;
特殊
如果是final修飾的,準(zhǔn)備階段就設(shè)定好初始化的值。

5 解析

作用:VM將常量池內(nèi)的符號引用替換為直接引用的過程。
符號引用和直接引用:
??符號引用:以一組符號來描述所引用的目標(biāo),符號可以是任何形式的字面量,與VM實現(xiàn)的內(nèi)存布局無關(guān),引用的目標(biāo)并不一定已經(jīng)加載到內(nèi)存中。
??直接引用:可以是直接指向目標(biāo)的指針、相對偏移量或是一個能間接定位到目標(biāo)的句柄。直接引用于VM實現(xiàn)的內(nèi)存布局相關(guān),引用的目標(biāo)必定已經(jīng)在內(nèi)存中存在。
??解析的符號引用:類或接口、字段、類方法、接口方法、方法類型、方法句柄和調(diào)用點限定符7類。分別對應(yīng)于常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info、CONSTANT_MethodType_info、CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info7種常量類型。

6 初始化

作用:類初始化階段是類加載過程最后一步,開始執(zhí)行類中定義的Java程序代碼(字節(jié)碼),是執(zhí)行類構(gòu)造器<clinit>()方法的過程。
<clinit>()方法:
1)<clinit>()是由編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)語句塊中的語句合并產(chǎn)生;
2)<clinit>()不需要顯式地調(diào)用父類構(gòu)造器,VM保證在調(diào)用<clinit>()之前就已經(jīng)執(zhí)行完父類的<clinit>(),所以VM中第一個被執(zhí)行的<clinit>()的類肯定是java.lang.Object;
3)父類中定義的靜態(tài)語句優(yōu)先于子類的變量賦值操作;
4)<clinit>()對于類或接口并不是必須的,若一個類中沒有靜態(tài)語句塊也沒有對變量的賦值操作,編譯器不會生成<clinit>()方法;
5)接口中不能使用靜態(tài)語句塊,但仍然有變量初始化賦值操作,所以接口會生成<clinit>()方法,但是,接口的<clinit>()不需要先執(zhí)行父接口的<clinit>()且實現(xiàn)類初始化時不會執(zhí)行接口的<clinit>()方法。
6)VM會保證一個類的<clinit>()方法在多線程環(huán)境中被正確地加鎖、同步。
初始化的觸發(fā)條件:
1)遇到new、getstatic、putstatic或invokestatic這4條字節(jié)碼指令時;
2)使用java.lang.reflect包的方法對類進(jìn)行反射調(diào)用時;
3)當(dāng)初始化一個類的時候,若發(fā)現(xiàn)其父類還沒有初始化時,需觸發(fā)父類的初始化;
4)虛擬機(jī)啟動時,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類),虛擬機(jī)會先初始化這個主類。

7 總結(jié)

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

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

  • 代碼編譯的結(jié)果從本地機(jī)器碼轉(zhuǎn)變?yōu)樽止?jié)碼,是存儲格式發(fā)展的一小步,確實編譯語言發(fā)展的一大步。 虛擬機(jī)把描述類的數(shù)據(jù)從...
    胡二囧閱讀 1,070評論 0 0
  • 1.加載,將二進(jìn)制字節(jié)流加載到方法區(qū),然后在java堆中實例化一個java.lang.Class類的對象2.驗證:...
    蒸汽飛船閱讀 847評論 0 0
  • 1.加載,將二進(jìn)制字節(jié)流加載到方法區(qū),然后在java堆中實例化一個java.lang.Class類的對象2.驗證:...
    蒸汽飛船閱讀 311評論 0 0
  • 接下來我們詳細(xì)講解一下Java虛擬機(jī)中類加載的全過程,也就是加載、驗證、準(zhǔn)備、解析和初始化這5個階段所執(zhí)行的具體動...
    史小猿閱讀 1,095評論 2 0
  • Java虛擬機(jī)整體篇幅如下: Java虛擬機(jī)基礎(chǔ)——1Java的內(nèi)存模型Java虛擬機(jī)基礎(chǔ)——2JVM運行時數(shù)據(jù)區(qū)...
    隔壁老李頭閱讀 2,961評論 1 16

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