溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JAVA虛擬機(jī)類(lèi)加載機(jī)制介紹

發(fā)布時(shí)間:2020-04-16 09:43:28 來(lái)源:億速云 閱讀:184 作者:小新 欄目:編程語(yǔ)言

這篇文章主要為大家詳細(xì)介紹了JAVA虛擬機(jī)類(lèi)加載機(jī)制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。

類(lèi)加載機(jī)制是把類(lèi)的數(shù)據(jù)從Class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的java類(lèi)型。這一系列的過(guò)程都是在程序運(yùn)行期間完成的。

類(lèi)加載器

類(lèi)加載器就是下圖中紅框的部分,它通過(guò)一個(gè)類(lèi)的全限定名來(lái)獲取描述此類(lèi)的二進(jìn)制字節(jié)流,從而將java類(lèi)動(dòng)態(tài)地加載進(jìn)JVM的內(nèi)存空間中。

JAVA虛擬機(jī)類(lèi)加載機(jī)制介紹

適用情景

對(duì)于一個(gè)非數(shù)組類(lèi)的加載階段,可以使用系統(tǒng)提供的引導(dǎo)類(lèi)加載器來(lái)完成,也可以由用戶自定義的類(lèi)加載器去完成。
對(duì)于數(shù)組類(lèi)而言,其由java虛擬機(jī)直接創(chuàng)建,不通過(guò)類(lèi)加載器。

雙親委派機(jī)制

雙親委派機(jī)制是類(lèi)加載所采取的一種方式。如果一個(gè)類(lèi)加載器收到了類(lèi)加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類(lèi),而是把這個(gè)請(qǐng)求委派給父類(lèi)加載器去完成。每一層的類(lèi)加載器均是如此。只有當(dāng)父加載器反饋?zhàn)约簾o(wú)法完成這個(gè)請(qǐng)求時(shí),子加載器才會(huì)嘗試自己去加載。

JAVA虛擬機(jī)類(lèi)加載機(jī)制介紹

類(lèi)比到現(xiàn)實(shí):小明想買(mǎi)一個(gè)玩具挖土機(jī),可他又不好意思直接張口說(shuō)。所以,發(fā)生了下面的對(duì)話。

小明去問(wèn)他爸爸:爸爸你有挖土機(jī)嗎?
爸爸說(shuō):沒(méi)有哎
接著爸爸問(wèn)爺爺:爸爸爸爸,你有挖土機(jī)嗎?
爺爺說(shuō):沒(méi)有哎
接著爺爺問(wèn)太爺爺:爸爸爸爸,你有挖土機(jī)嗎?
太爺爺說(shuō):我也沒(méi)有。讓重孫子去買(mǎi)一個(gè)吧。
結(jié)果小明就高高興興地自己去買(mǎi)了一個(gè)玩具挖土機(jī)。

分類(lèi)

啟動(dòng)類(lèi)加載器是使用C++實(shí)現(xiàn)的,是虛擬機(jī)自身的一部分。
其它類(lèi)加載器是由java語(yǔ)言實(shí)現(xiàn)的,獨(dú)立于虛擬機(jī)外部,并且全都繼承自抽象類(lèi)java.lang.ClassLoader。

好處

以String類(lèi)為例。就算是用戶自己寫(xiě)了一個(gè)String類(lèi)的實(shí)現(xiàn),那對(duì)此類(lèi)進(jìn)行加載時(shí),也只會(huì)委派給啟動(dòng)類(lèi)加載器來(lái)對(duì)JDK中原本的String類(lèi)進(jìn)行加載,而自定義的String類(lèi)永遠(yuǎn)不會(huì)被調(diào)用。這樣保證了系統(tǒng)的安全。

什么時(shí)候進(jìn)行類(lèi)加載?

有且只有以下5種方式必須立即對(duì)類(lèi)進(jìn)行加載

(1)使用new實(shí)例化對(duì)象的時(shí)候;讀取或配置一個(gè)類(lèi)的靜態(tài)字段(被final修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時(shí)候;調(diào)用一個(gè)類(lèi)的靜態(tài)方法的時(shí)候。

(2)使用java.lang.reflect包的方法對(duì)類(lèi)進(jìn)行反射調(diào)用的時(shí)候。如果類(lèi)沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其初始化。

(3)當(dāng)初始化一個(gè)類(lèi)的時(shí)候,如果發(fā)現(xiàn)其父類(lèi)還沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類(lèi)的初始化。

(4)當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(lèi)(包含main()方法的類(lèi)),虛擬機(jī)會(huì)先初始化這個(gè)主類(lèi)

類(lèi)加載過(guò)程詳述

類(lèi)加載過(guò)程分為5步。大部分都是由虛擬機(jī)主導(dǎo)和控制的,除了以下兩種情形:

在加載階段

開(kāi)發(fā)人員可以通過(guò)自定義類(lèi)加載器參與

在初始化階段

會(huì)執(zhí)行開(kāi)發(fā)人員的代碼去初始化類(lèi)變量和其它資源

1、加載

虛擬機(jī)需要完成的事情:
(1) 通過(guò)一個(gè)類(lèi)的全限定名來(lái)獲取定義此類(lèi)的二進(jìn)制字節(jié)流。
(2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。
(3)在內(nèi)存中生成一個(gè)代表這個(gè)類(lèi)的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類(lèi)的各種數(shù)據(jù)的訪問(wèn)入口。

JAVA虛擬機(jī)類(lèi)加載機(jī)制介紹

2、驗(yàn)證

驗(yàn)證的目的是確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,不會(huì)危害虛擬機(jī)自身的安全。
其分為4個(gè)步驟:文件格式驗(yàn)證,元數(shù)據(jù)驗(yàn)證,字節(jié)碼驗(yàn)證,符號(hào)引用驗(yàn)證。其中文件格式驗(yàn)證是直接對(duì)字節(jié)流進(jìn)行操作的,其余3項(xiàng)是在方法區(qū)中進(jìn)行的。

3、準(zhǔn)備

此階段是正式為類(lèi)變量分配內(nèi)存并設(shè)置類(lèi)變量初始值的階段。其是在方法區(qū)中進(jìn)行分配的。有兩個(gè)注意點(diǎn):

(1)此時(shí)只是對(duì)類(lèi)變量(被static修飾的變量)進(jìn)行內(nèi)存分配,而不是對(duì)象變量。給對(duì)象分配內(nèi)存是在對(duì)象實(shí)例化時(shí),隨著對(duì)象一起分配到j(luò)ava堆中。

(2)如果一個(gè)類(lèi)變量沒(méi)有被final修飾,則其初始值是數(shù)據(jù)類(lèi)型的零值。比如int類(lèi)型的是0,boolean類(lèi)型的是false。舉個(gè)例子來(lái)說(shuō)明:

public static int value=123;

在準(zhǔn)備階段過(guò)后的初始值為0而不是123,因?yàn)檫@個(gè)時(shí)候尚未開(kāi)始執(zhí)行任何java方法,而把value賦值為123的putstatic指令是程序被編譯后,存放于類(lèi)構(gòu)造器< clinit >()方法之中。所以把value賦值為123的動(dòng)作將在初始化階段才會(huì)執(zhí)行。

public static final int value=123;

此時(shí)因?yàn)橛衒inal,所以在準(zhǔn)備階段value就已經(jīng)被賦值為123了。

4、解析

解析階段是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程。可對(duì)類(lèi)或接口、字段、類(lèi)方法、接口方法等進(jìn)行解析。

符號(hào)引用是什么:

符號(hào)引用就是包含類(lèi)的信息,方法名,方法參數(shù)等信息的字符串,它供實(shí)際使用時(shí)在該類(lèi)的方法表中找到對(duì)應(yīng)的方法。

直接引用是什么:

直接引用就是偏移量,通過(guò)偏移量可以直接在該類(lèi)的內(nèi)存區(qū)域中找到方法字節(jié)碼的起始位置。
符號(hào)引用是告訴你此方法的一些特征,你需要通過(guò)這些特征去尋找對(duì)應(yīng)的方法。直接引用就是直接告訴你此方法在哪。

5、初始化

此階段用于初始化類(lèi)變量和其它資源,是執(zhí)行類(lèi)構(gòu)造器< clinit >()方法的過(guò)程,此時(shí)才是真正開(kāi)始執(zhí)行類(lèi)中定義的java程序代碼。

以上就是JAVA虛擬機(jī)類(lèi)加載機(jī)制介紹的詳細(xì)內(nèi)容了,看完之后是否有所收獲呢?如果想了解更多相關(guān)內(nèi)容,歡迎來(lái)億速云行業(yè)資訊!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI