類加載運(yùn)行機(jī)制
類加載形如把.class文件,加載到內(nèi)存中,得到類對(duì)象這樣的過(guò)程
類加載一共分為五個(gè)步驟:
- 加載
- 驗(yàn)證
- 準(zhǔn)備
- 解析
- 初始化
加載
類加載的第一步是將編譯好的 Java 類的字節(jié)碼文件加載到 Java 虛擬機(jī)(JVM)中。類加載器會(huì)根據(jù)類的名稱找到對(duì)應(yīng)的字節(jié)碼文件,并將其讀取到內(nèi)存中。
驗(yàn)證
在驗(yàn)證階段,虛擬機(jī)會(huì)對(duì)加載的字節(jié)碼文件進(jìn)行合法性驗(yàn)證,包括文件格式的驗(yàn)證、驗(yàn)證字節(jié)碼的正確性和安全性等。這一步主要用于確保 class 文件不會(huì)引起虛擬機(jī)的錯(cuò)誤或安全問(wèn)題。
準(zhǔn)備
在準(zhǔn)備階段,虛擬機(jī)會(huì)為加載的類分配內(nèi)存空間,并設(shè)置類的默認(rèn)初始值。這些初始值包括零值(0、false或null)或者用戶所設(shè)置的初始值。
解析
解析階段是將常量池中的符號(hào)引用轉(zhuǎn)換成直接引用的過(guò)程。符號(hào)引用包括類、接口、字段和方法等的引用。解析操作的主要目的是為了創(chuàng)建對(duì)應(yīng)的直接引用,以便于后續(xù)的內(nèi)存空間分配、類的初始化和方法的調(diào)用等操作。
在 Java 語(yǔ)言中,當(dāng)我們?cè)诖a中引用一個(gè)類、接口、字段或方法時(shí),實(shí)際上是通過(guò)符號(hào)引用來(lái)表示的。符號(hào)引用是一種符號(hào)化的描述方式,它并不指向具體的內(nèi)存地址或偏移量,而是通過(guò)符號(hào)的形式來(lái)描述所引用的目標(biāo)。
舉個(gè)例子,假設(shè)有以下代碼片段:
public class ClassA {
public void methodA() {
ClassB b = new ClassB();
b.methodB();
}
}
public class ClassB {
public void methodB() {
System.out.println("Method B is called");
}
}
在ClassA
的methodA
方法中,我們創(chuàng)建了一個(gè)ClassB
的實(shí)例,并調(diào)用了它的methodB
方法。
在解析階段,虛擬機(jī)會(huì)進(jìn)行如下的符號(hào)引用轉(zhuǎn)換為直接引用的過(guò)程:
- 虛擬機(jī)會(huì)解析
ClassA
對(duì)ClassB
的符號(hào)引用,找到對(duì)應(yīng)的類ClassB
的描述符和其他信息。 - 虛擬機(jī)會(huì)在內(nèi)存中為
ClassB
分配空間,創(chuàng)建ClassB
的實(shí)例對(duì)象。 - 虛擬機(jī)會(huì)將
b
變量與實(shí)際的內(nèi)存地址關(guān)聯(lián)起來(lái),這樣可以通過(guò)b
來(lái)訪問(wèn)ClassB
對(duì)象。 - 虛擬機(jī)會(huì)通過(guò)
b.methodB()
來(lái)調(diào)用ClassB
的methodB
方法,這里的methodB
是一個(gè)直接引用。
所以,在解析階段,虛擬機(jī)將符號(hào)引用轉(zhuǎn)換為直接引用,這樣就能夠通過(guò)直接引用來(lái)訪問(wèn)和使用目標(biāo)類的字段或方法。通過(guò)這種方式,虛擬機(jī)可以動(dòng)態(tài)地解析和鏈接類之間的關(guān)系,實(shí)現(xiàn)類的動(dòng)態(tài)綁定和調(diào)用。
初識(shí)化
在初始化階段,虛擬機(jī)會(huì)執(zhí)行類的初始化代碼,例如靜態(tài)變量的賦值和靜態(tài)代碼塊的執(zhí)行等。
這一階段的觸發(fā)條件包括:
- 類的實(shí)例被創(chuàng)建;
- 類的靜態(tài)方法被調(diào)用;
- 類中的靜態(tài)字段被賦值。
類的初始化是類加載的最后一個(gè)步驟。
雙親委派模型
雙親委派模型(又稱為雙親委派機(jī)制)是Java類加載機(jī)制中的一種設(shè)計(jì)思想和實(shí)現(xiàn)方式。
類加載機(jī)制是Java虛擬機(jī)(JVM)加載類的過(guò)程,而雙親委派模型是指在類加載過(guò)程中,JVM通過(guò)委派的方式來(lái)從不同的類加載器去加載類。這個(gè)機(jī)制主要用于確保類的一致性、安全性和避免重復(fù)加載。
在JVM中,有三個(gè)類加載器:
- BootStrap ClassLoader 負(fù)責(zé)加載java標(biāo)志庫(kù)中的類
- Extension ClassLoader 負(fù)責(zé)加載一些非標(biāo)準(zhǔn)的但是是Sun/Oracle 擴(kuò)展的庫(kù)的類
- Application ClassLpader 負(fù)責(zé)加載項(xiàng)目中自己寫(xiě)的類以及第三方庫(kù)中的一些類
一個(gè)類加載器收到了類加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器去完成,每一個(gè)層次的類加載器都是如此,因此所有的加載請(qǐng)求最 終都應(yīng)該傳送到最頂層的啟動(dòng)類加載器中,只有當(dāng)父加載器反饋?zhàn)约簾o(wú) 法完成這個(gè)加載請(qǐng)求(它的搜索范圍中沒(méi)有找到所需的類)時(shí),子加載器才會(huì)嘗試自己去完成加載。
雙親委派模型基于以下幾個(gè)原則:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-556384.html
- 父類加載器優(yōu)先:如果一個(gè)類需要被加載,JVM首先會(huì)把這個(gè)任務(wù)委派給父類加載器來(lái)完成。
- 雙親委派:父類加載器在接收到加載請(qǐng)求后,會(huì)先檢查自己是否已經(jīng)加載了這個(gè)類。如果已經(jīng)加載,則直接返回該類的Class對(duì)象。如果沒(méi)有加載,則將加載請(qǐng)求向上委派給父類的父類加載器,以此類推,直到頂層的啟動(dòng)類加載器。只有當(dāng)父類加載器不能完成加載任務(wù)時(shí),子加載器才會(huì)嘗試自己去加載。
3.** 緩存機(jī)制:如果一個(gè)類被某個(gè)加載器加載成功后,這個(gè)加載器會(huì)將加載結(jié)果緩存起來(lái),下次再加載同樣的類時(shí)直接返回緩存的結(jié)果**。
通過(guò)雙親委派模型,可以有效地避免類的重復(fù)加載和類的不一致性問(wèn)題。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-556384.html
到了這里,關(guān)于解析Java類加載的運(yùn)行機(jī)制和雙親委派模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!