JVM 雙親委派模型
1. 前言
上節(jié)課程的小結(jié)部分提到,雙親委派模型是加載(Loading)步驟中所使用的模型,上節(jié)內(nèi)容為本節(jié)內(nèi)容的基礎(chǔ)知識(shí),學(xué)習(xí)本節(jié)內(nèi)容之前,要確保已經(jīng)掌握了上節(jié)所講解的內(nèi)容。本節(jié)主要知識(shí)點(diǎn)如下:
- 了解雙親委派模型的示意圖,是本節(jié)課程的基礎(chǔ)知識(shí);
- 掌握雙親委派模型的工作原理,并結(jié)合示意圖進(jìn)行理解,為本節(jié)內(nèi)容的核心知識(shí)點(diǎn);
- 舉出三個(gè)不同類型的案例供學(xué)習(xí)者參考,更深入的了解雙親委派模型的工作原理,為本節(jié)內(nèi)容的重點(diǎn)內(nèi)容;
2. 雙親委派模型
在講解雙親委派模型之前,我們先來看看雙親委派模型的示意圖,相信看到如下示意圖中的模塊信息,學(xué)習(xí)者會(huì)感到莫名的親切感。示意圖如下:
上圖中的親切感來自哪里呢?我們可以看到在雙親委派模型中,有三種類加載器是我們上節(jié)課程中所講解的,有了上節(jié)課程的知識(shí)積淀,再理解雙親委派模型會(huì)非常的容易。
雙親委派模型原理:
- 向上委托:如果一個(gè)類加載器收到了類加載請(qǐng)求,它并不會(huì)自己先去加載,而是把這個(gè)請(qǐng)求委托給父類的加載器去執(zhí)行,如果父類加載器還存在其父類加載器,則進(jìn)一步向上委托,依次遞歸,請(qǐng)求最終將到達(dá)頂層的啟動(dòng)類加載器。如果父類加載器可以完成類加載任務(wù),就成功返回;
- 向下委派:倘若父類加載器無(wú)法完成此加載任務(wù),子加載器才會(huì)嘗試自己去加載,這就是雙親委派模式。
如果對(duì)于原理性的描述還是比較模糊的話,不要著急,我們繼續(xù)學(xué)習(xí)下邊的內(nèi)容,通過案例體會(huì)雙親委派模型的原理。
3. 案例 1:加載 /jre/lib/resources.jar
通過上節(jié)課程的學(xué)習(xí),我們能夠知道 /jre/lib/resources.jar 是需要被啟動(dòng)(BootStrap)類加載器加載的核心類庫(kù),那么我們來看看它的加載流程圖。
加載流程圖:根據(jù)雙親委派模型,我們來看下 resources.jar 的完整加載過程。
從上圖中我們可以看到,對(duì)于核心類庫(kù) resources.jar 的加載,分為以下 4 步:
- 步驟 1:resources.jar 會(huì)先通過自定義類加載器(前提是我們實(shí)現(xiàn)了自定義類加載器),自定義類加載器不會(huì)做處理,直接向上委托給系統(tǒng)(System Application)類加載器;
- 步驟 2:系統(tǒng)(System Application)類加載器接到委托后,也不做任何處理,直接向上委托給擴(kuò)展(Extension)類加載器;
- 步驟 3:擴(kuò)展(Extension)類加載器接到委托后,也不做任何處理,直接向上委托給啟動(dòng)(Bootstrap)類加載器;
- 步驟 4:?jiǎn)?dòng)(Bootstrap)類加載器接到委托后,發(fā)現(xiàn) resources.jar 是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行加載,最后成功加載了 resources.jar。
4. 案例 2:加載 /jre/lib/ext/cldrdata.jar
通過上節(jié)課程的學(xué)習(xí),我們能夠知道 /jre/lib/ext/cldrdata.jar 是需要被擴(kuò)展(Extension)類加載器加載的核心類庫(kù),那么我們來看看它的加載流程圖。
加載流程圖:根據(jù)雙親委派模型,我們來看下 cldrdata.jar 的完整加載過程。
從上圖中我們可以看到,對(duì)于核心類庫(kù) cldrdata.jar 的加載,分為以下 5 步:
- 步驟 1:cldrdata.jar 會(huì)先通過自定義類加載器(前提是我們實(shí)現(xiàn)了自定義類加載器),自定義類加載器不會(huì)做處理,直接向上委托給系統(tǒng)(System Application)類加載器;
- 步驟 2:系統(tǒng)(System Application)類加載器接到委托后,也不做任何處理,直接向上委托給擴(kuò)展(Extension)類加載器;
- 步驟 3:擴(kuò)展(Extension)類加載器接到委托后,也不做任何處理,直接向上委托給啟動(dòng)(Bootstrap)類加載器;
- 步驟 4:?jiǎn)?dòng)(Bootstrap)類加載器接到委托后,發(fā)現(xiàn) cldrdata.jar 不是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行向下委派,委派給擴(kuò)展(Extension)類加載器;
- 步驟 5:擴(kuò)展(Extension)類加載器接到委派后,發(fā)現(xiàn) cldrdata.jar 是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行加載,最后成功加載了 cldrdata.jar。
Tips:我們可以看到,在向上委托的過程中,cldrdata.jar 雖然在步驟 3 已經(jīng)達(dá)到了擴(kuò)展(Extension)類加載器,但是由于擴(kuò)展(Extension)類加載器需要遵循向上委托的原則,必須要將 cldrdata.jar 向上委托給啟動(dòng)(Bootstrap)類加載器,直到啟動(dòng)(Bootstrap)類加載器向下委派 cldrdata.jar 到擴(kuò)展(Extension)類加載器才進(jìn)行類庫(kù)的加載。
5. 案例 3:加載 /jre/lib/plugin.jar
通過上節(jié)課程的學(xué)習(xí),我們能夠知道 /jre/lib/plugin.jar 是需要被系統(tǒng)(System Application)類加載器加載的核心類庫(kù),那么我們來看看它的加載流程圖。
加載流程圖:根據(jù)雙親委派模型,我們來看下 plugin.jar 的完整加載過程。
從上圖中我們可以看到,對(duì)于核心類庫(kù) plugin.jar 的加載,分為以下 6 步:
- 步驟 1:plugin.jar 會(huì)先通過自定義類加載器(前提是我們實(shí)現(xiàn)了自定義類加載器),自定義類加載器不會(huì)做處理,直接向上委托給系統(tǒng)(System Application)類加載器;
- 步驟 2:系統(tǒng)(System Application)類加載器接到委托后,也不做任何處理,直接向上委托給擴(kuò)展(Extension)類加載器;
- 步驟 3:擴(kuò)展(Extension)類加載器接到委托后,也不做任何處理,直接向上委托給啟動(dòng)(Bootstrap)類加載器;
- 步驟 4:?jiǎn)?dòng)(Bootstrap)類加載器接到委托后,發(fā)現(xiàn) plugin.jar 不是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行向下委派,委派給擴(kuò)展(Extension)類加載器;
- 步驟 5:擴(kuò)展(Extension)類加載器接到委派后,發(fā)現(xiàn) plugin.jar 也不是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行向下委派,委派給系統(tǒng)(System Application)類加載器;
- 步驟 6:系統(tǒng)(System Application)類加載器接到委派后,發(fā)現(xiàn) plugin.jar 是自己負(fù)責(zé)加載的核心類庫(kù),于是進(jìn)行加載,最后成功加載了 plugin.jar。
Tips:類似于案例 2 的講解,雖然 plugin.jar 是系統(tǒng)(System Application)類加載器負(fù)責(zé)加載的,但是要遵循向上委托的原則,因此在步驟 2 不能夠?qū)崟r(shí)加載,只能等待父加載器向下委派時(shí)加載。
6. 小結(jié)
通過對(duì)雙親委派模型的講解,我們了解到了雙親委派模型的定義以及原理,并通過 3 個(gè)案例詳細(xì)的講述了在雙親委派模型下是如何進(jìn)行的類庫(kù)的加載。
通篇皆為重點(diǎn)內(nèi)容,所有的內(nèi)容都是圍繞雙親委派模型的原理展開的,需要學(xué)習(xí)者仔細(xì)品味案例,掌握雙親委派模型的原理。