溫馨提示×

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

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

Java類加載機(jī)制有哪些內(nèi)容

發(fā)布時(shí)間:2021-12-24 16:31:17 來源:億速云 閱讀:110 作者:iii 欄目:編程語言

這篇文章主要介紹“Java類加載機(jī)制有哪些內(nèi)容”,在日常操作中,相信很多人在Java類加載機(jī)制有哪些內(nèi)容問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java類加載機(jī)制有哪些內(nèi)容”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

一:前言

Java語言的類型可以分為兩大類:基本類型和引用類型。

基本類型包括byte,short,int,long,float,double,boolean,char。

引用類型包括類,接口,數(shù)組類和泛型參數(shù)。由于泛型參數(shù)會(huì)在編譯過程中被擦除,因此Java虛擬機(jī)實(shí)際上只有前三種。在類,接口和數(shù)組類中,數(shù)組類是由Java虛擬機(jī)直接生成的,其它兩種則有對(duì)應(yīng)的字節(jié)流。

Java類加載機(jī)制有哪些內(nèi)容

二:加載

1.加載,就是查找字節(jié)流,并且據(jù)此生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象的過程。注意這里字節(jié)流不一定非得要從一個(gè)Class文件獲取,這里既可以從ZIP包中讀取(比如從jar包和war包中讀?。部梢栽谶\(yùn)行時(shí)計(jì)算生成(動(dòng)態(tài)代理),也可以由其它文件生成(比如將JSP文件轉(zhuǎn)換成對(duì)應(yīng)的Class類)。加載的信息存儲(chǔ)在JVM的方法區(qū)。

2.對(duì)于數(shù)組類來說,它并沒有對(duì)應(yīng)的字節(jié)流,而是由Java虛擬機(jī)直接生成的。對(duì)于其它的類來說,Java虛擬機(jī)則需要借助類加載器來完成查找字節(jié)流的過程。

3.類加載器有兩種,一種是啟動(dòng)類加載器,其它的類加載器都是java.lang.ClassLoader的子類。啟動(dòng)類加載器是由C++實(shí)現(xiàn)的,沒有對(duì)應(yīng)的Java對(duì)象,因此在Java中只能用null代替。除了啟動(dòng)類加載器之外,另外兩個(gè)重要的類加載器是擴(kuò)展類加載器和應(yīng)用類加載器,均由Java核心類庫(kù)提供。 啟動(dòng)類加載器加載最為基礎(chǔ),最為重要的類,如JRE的lib目錄下jar包中的類;擴(kuò)展類加載器的父類是啟動(dòng)類加載器,它負(fù)責(zé)加載相對(duì)次要,但又通用的類,如JRE的lib/ext目錄下jar包中的類;應(yīng)用類加載器的父類加載器則是擴(kuò)展類加載器,它負(fù)責(zé)加載應(yīng)用程序路徑下的類。

4.JVM通過雙親委派模型進(jìn)行類的加載,當(dāng)然我們也可以通過繼承java.lang.ClassLoader實(shí)現(xiàn)自定義的類加載器。當(dāng)一個(gè)類加載器收到類加載任務(wù),會(huì)先交給其父類加載器去完成,因此最終加載任務(wù)都會(huì)傳遞到頂層的啟動(dòng)類加載器,只有當(dāng)父類加載器無法完成加載任務(wù)時(shí),才會(huì)嘗試執(zhí)行加載任務(wù)。

采用雙親委派的一個(gè)好處是比如加載位于rt.jar包中的類java.lang.Object,不管是哪個(gè)加載器加載這個(gè)類,最終都是委托給頂層的啟動(dòng)類加載器進(jìn)行加載,這樣就保證了使用不同的類加載器最終得到的都是同樣一個(gè)Object對(duì)象。

三:鏈接

鏈接,是指將創(chuàng)建成的類合并至Java虛擬機(jī)中,使之能夠執(zhí)行的過程。它分為驗(yàn)證,準(zhǔn)備和解析三個(gè)階段。

1.驗(yàn)證

 該階段的目的在于確保被加載類能夠滿足Java虛擬機(jī)的約束條件。

2.準(zhǔn)備

該階段的目的是為被加載類的靜態(tài)字段分配內(nèi)存,即在方法區(qū)中分配這些變量所使用的內(nèi)存空間。Java代碼中對(duì)靜態(tài)字段的具體初始化,則會(huì)在稍后的初始化階段中進(jìn)行。

3.解析

 在class文件被加載至Java虛擬機(jī)前,這個(gè)類無法知道其它類及其方法,字段所對(duì)應(yīng)的具體地址。甚至不知道自己方法,字段的地址。因此,每當(dāng)需要引用這些成員時(shí),

Java編譯器會(huì)生成一個(gè)符號(hào)引用。在運(yùn)行階段,這個(gè)符號(hào)引用一般能夠無歧義地定位到具體目標(biāo)上。解析階段的目的,正是將這些符號(hào)引用解析為實(shí)際引用。如果符號(hào)引用

指向一個(gè)未被加載的類,或者未被加載類的字段或方法,那么解析將觸發(fā)這個(gè)類的加載。

四:初始化

1.初始化階段是類加載最后一個(gè)階段,前面的類加載階段之后,除了在加載階段可以自定義類加載器以外,其它操作都由JVM主導(dǎo)。到了初始階段,才開始真正執(zhí)行類中定義的Java程序代碼。

2.在 Java 代碼中,如果要初始化一個(gè)靜態(tài)字段,我們可以在聲明時(shí)直接賦值,也可以在靜態(tài)代碼塊中對(duì)其賦值。

如果直接賦值的靜態(tài)字段被 final 所修飾,并且它的類型是基本類型或字符串時(shí),那么該字段便會(huì)被 Java 編譯器標(biāo)記成常量值(ConstantValue),其初始化直接由 Java 虛擬機(jī)完成。除此之外的直接賦值操作,以及所有靜態(tài)代碼塊中的代碼,則會(huì)被 Java 編譯器置于同一方法中,并把它命名為 < clinit >。

類加載的最后一步是初始化,便是為標(biāo)記為常量值的字段賦值,以及執(zhí)行 < clinit > 方法的過程。Java 虛擬機(jī)會(huì)通過加鎖來確保類的 < clinit > 方法僅被執(zhí)行一次。

只有當(dāng)初始化完成之后,類才正式成為可執(zhí)行的狀態(tài)。

3.JVM 規(guī)范枚舉類的初始化被觸發(fā)的情況:

a.當(dāng)虛擬機(jī)啟動(dòng)時(shí),初始化用戶指定的主類;

b.當(dāng)遇到用以新建目標(biāo)類實(shí)例的 new 指令時(shí),初始化 new 指令的目標(biāo)類;

c.當(dāng)遇到調(diào)用靜態(tài)方法的指令時(shí),初始化該靜態(tài)方法所在的類;

d.當(dāng)遇到訪問靜態(tài)字段的指令時(shí),初始化該靜態(tài)字段所在的類;

e.子類的初始化會(huì)觸發(fā)父類的初始化;

f.如果一個(gè)接口定義了 default 方法,那么直接實(shí)現(xiàn)或者間接實(shí)現(xiàn)該接口的類的初始化,會(huì)觸發(fā)該接口的初始化;

j.使用反射 API 對(duì)某個(gè)類進(jìn)行反射調(diào)用時(shí),初始化這個(gè)類;

h.當(dāng)初次調(diào)用 MethodHandle 實(shí)例時(shí),初始化該 MethodHandle 指向的方法所在的類。

到此,關(guān)于“Java類加載機(jī)制有哪些內(nèi)容”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(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