目錄
1、加載 (加載字節(jié)碼文件,生成.class對(duì)象)
2、驗(yàn)證(驗(yàn)證Class文件是否符合規(guī)范)?
3、準(zhǔn)備 (為靜態(tài)變量分配內(nèi)存并設(shè)置變量初始值)
4、解析(初始化常量池中的一些常量)?
5、初始化(初始化對(duì)象,并為靜態(tài)變量賦值)?
總結(jié):
雙親委派模型:??
JVM的類加載器(主要有3個(gè)):?
標(biāo)準(zhǔn)庫(kù)中的String類是怎樣被加載的??
自定義的類如何加載??
類加載一定要使用雙親委派模型嗎??
為什么Tomcat不使用雙親委派模型??
Tomcat是怎么實(shí)現(xiàn)webapps下各個(gè)web應(yīng)用程序的隔離的?
類加載過程簡(jiǎn)單來說就是把.class文件加載到內(nèi)存中構(gòu)造出類對(duì)象?
JVM的類加載過程要經(jīng)歷以下幾個(gè)階段:加載->連接->初始化?
其中連接階段可以細(xì)分成:驗(yàn)證->準(zhǔn)備->解析
所以也可以說JVM的類加載過程是這幾個(gè)階段:?加載->驗(yàn)證->準(zhǔn)備->解析->初始化
1、加載 (加載字節(jié)碼文件,生成.class對(duì)象)
首先要進(jìn)行加載的過程。加載過程就是要找到.class文件,打開并讀取它。在這個(gè)過程中要先從.class文件中獲取到這個(gè)類的二進(jìn)制字節(jié)流,然后將這個(gè)字節(jié)流代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu),最后在內(nèi)存中生成一個(gè)代表該類的java.long.Class對(duì)象,然后把這個(gè)放到方法區(qū),作為該類的數(shù)據(jù)訪問接口。?
二進(jìn)制的.class文件包含內(nèi)容:
詳情見Java虛擬機(jī)規(guī)范手冊(cè):https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html?
2、驗(yàn)證(驗(yàn)證Class文件是否符合規(guī)范)?
在進(jìn)行讀取前,要先驗(yàn)證Class文件字節(jié)流中包含的信息是否符合Java虛擬機(jī)規(guī)范的約束條件,?驗(yàn)證的內(nèi)容包括:文件格式,字節(jié)碼,符號(hào)引用
3、準(zhǔn)備 (為靜態(tài)變量分配內(nèi)存并設(shè)置變量初始值)
準(zhǔn)備階段是正式為類中的屬性(static修飾的變量)分配內(nèi)存和進(jìn)行初始值的設(shè)定
如:public static int num=123;在準(zhǔn)備階段并不會(huì)對(duì)num進(jìn)行賦值123,而是先設(shè)定num=0;
4、解析(初始化常量池中的一些常量)?
前面我們說到.class文件中包含的內(nèi)容,在這一階段,JVM會(huì)將符號(hào)引用轉(zhuǎn)化為直接引用,也就是在這一階段,會(huì)對(duì)常量進(jìn)行一個(gè)初始化。
5、初始化(初始化對(duì)象,并為靜態(tài)變量賦值)?
在這一階段,Java虛擬機(jī)開始真正的執(zhí)行類中的代碼,進(jìn)行對(duì)象的初始化,并且為靜態(tài)變量賦值,比如前面的?num 就會(huì)在這一階段被賦值為123,而不是原來的0了。
總結(jié):
雙親委派模型:??
雙親委派模型屬于一種類加載的機(jī)制。
前面我們說到了類加載的過程經(jīng)歷了加載-> 連接->初始化的過程。其中加載的過程是加載字節(jié)碼文件,生成.class對(duì)象。在這個(gè)加載的過程中類加載器發(fā)揮著至關(guān)重要的作用,而雙親委派模型就是描述類加載器是如何根據(jù)全限定名(類名+包名,如java.long.String)找到.class文件的過程,這個(gè)過程屬于加載過程的靠前的階段。
JVM的類加載器(主要有3個(gè)):?
JVM的類加載器主要是下面這3個(gè):
BootSharpClassLoader(負(fù)責(zé)加載標(biāo)準(zhǔn)庫(kù)當(dāng)中的類(如List,String))
ExtensionClassLoader(負(fù)責(zé)加載JDK擴(kuò)展庫(kù)當(dāng)中的類)
ApplicationClassLoader(負(fù)責(zé)加載當(dāng)前目錄當(dāng)中的類)?
除此之外,用戶也可以自定義類加載器:User-DefinedClassLoader,一般沒有使用自定義加載器,所以默認(rèn)就是上面的那3種類加載器。每個(gè)類加載器負(fù)責(zé)加載自己負(fù)責(zé)的目錄。?
下圖來源于博客:?JVM類加載器-CSDN博客
雙親委派模型就是描述了上述的類加載器之間是怎么配合的?。
例子(沒有自定義類加載器):
標(biāo)準(zhǔn)庫(kù)中的String類是怎樣被加載的??
第一步:程序啟動(dòng),進(jìn)入ApplicationClassLoader類加載器
第二步:在ApplicationClassLoader中檢查其父類加載器ExtensionClassLoader是否被加載過,如果沒有加載過就進(jìn)入到ExtensionClassLoader中
第三步:在ExtensionClassLoader中檢查最高父類加載器BootSharpClassLoader是否加載過,沒有就進(jìn)入BootSharpClassLoader中。?
最后在BootSharpClassLoader中查找標(biāo)準(zhǔn)庫(kù)的目錄:java.long.String,完成String的加載。
自定義的類如何加載??
如果是自定義的類,也會(huì)經(jīng)歷上述過程,但是由于在BootSharpClassLoader目錄中無法找到該自定義的類就會(huì)回到上一級(jí)ExtensionClassLoader中進(jìn)行加載,如果還是找不到就會(huì)到上一級(jí)ApplicationClassLoader當(dāng)中進(jìn)行加載,然后再當(dāng)前目錄中找到了自定義的類進(jìn)行加載。
?如果在最后沒有成功加載就會(huì)拋出ClassNotFoundException。
雙親委派模型的優(yōu)勢(shì):
當(dāng)用戶自定義的類與標(biāo)準(zhǔn)庫(kù)中的類的全限定名重復(fù)了,依然可以準(zhǔn)確的加載標(biāo)準(zhǔn)庫(kù)中的類,而不是自定義的類,比如自定義一個(gè)和標(biāo)準(zhǔn)庫(kù)中的java.long.String的一樣的類,當(dāng)類加載器加載到BootSharpClassLoader的時(shí)候就不會(huì)再返回了,就加載的是標(biāo)準(zhǔn)庫(kù)中的類。??
類加載一定要使用雙親委派模型嗎??
不一定,因?yàn)殡p親委派模型只是類加載機(jī)制中的一種,是適用于JVM的類加載的,而像Tomcat加載webapps中的類則沒有使用雙親委派模型。
為什么Tomcat不使用雙親委派模型??
首先Tomcat中的webapps下面有很多的web應(yīng)用程序。
第一個(gè)原因:隔離性,為了保證每個(gè)web應(yīng)用程序之間互不干擾,可以相互獨(dú)立互不干擾的加載和銷毀各自的類,不會(huì)因?yàn)閣eb程序因?yàn)橹孛蛘甙姹静煌仍蛟斐蓻_突。
第二個(gè)原因:方便動(dòng)態(tài)的重新加載已經(jīng)加載過的類,使得開發(fā)和部署的效率更高。?文章來源:http://www.zghlxwxcb.cn/news/detail-419034.html
Tomcat是怎么實(shí)現(xiàn)webapps下各個(gè)web應(yīng)用程序的隔離的?
Tomcat自定義了一個(gè)webapp類加載器,并且給每一個(gè)web應(yīng)用程序都創(chuàng)建一個(gè)類加載器,所以不同的類加載器加載的就是不同的類了。?文章來源地址http://www.zghlxwxcb.cn/news/detail-419034.html
到了這里,關(guān)于JVM的類加載的過程以及雙親委派模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!