Java虛擬機 雙親委派機制 的工作原理

類的加載:
加載指的是將類的class文件讀入到內(nèi)存,并為之創(chuàng)建一個java.lang.Class對象,也就是說,當程序中使用任何類時,系統(tǒng)都會為之建立一個java.lang.Class對象。
類的加載由類加載器完成,類加載器通常由JVM提供,這些類加載器也是前面所有程序運行的基礎,JVM提供的這些類加載器通常被稱為系統(tǒng)類加載器。除此之外,開發(fā)者可以通過繼承ClassLoader基類來創(chuàng)建自己的類加載器。
雙親委派機制 的工作原理
1)如果一個類加載器收到了類加載請求,它并不會自己先去加載,而是把這個請求委托給父類的加載器去執(zhí)行。
2)如果父類加載器還存在其父類加載器,則進一步向上委托,依次遞歸請求最終將到達頂層的啟動類加載器。
3)如果父類加載器可以完成類加載任務,就成功返回,倘若父類加載器無法完成此加載任務,子加載器才會嘗試自己去加載,這就是雙親委派模式。

案例舉例:
下面我們不妨通過一個例子來幫助我們理解一下雙親委派機制:
首先我們在工程下創(chuàng)建一個java.lang包,包下新建一個String類(我們在此只做示范,實際代碼中不推薦同學們以此命名)

在String類中加入以下代碼:
package java.lang;
public?class?String?{
??static?{
????System.out.println("我是java.lang包下的String類");
??}
}我們可以將其看成一個我們手寫的一個”偽裝“的String類
接著我們在工程的另一個包下新建一個StringTest類

其中加入以下方法:
package Test;
public?class?StringTest?{
??public?static?void?main(String[] args) {
????String str=new?java.lang.String();
????System.out.println("開始測試。。。");
??}
}那么問題來了,當我們new java.lang包下的String類時,我們new的是java系統(tǒng)包下的String呢還是我們剛剛自己定義的String類呢?
換言之,我們在上面定義的String類中加入的static靜態(tài)代碼塊會不會執(zhí)行呢??
請看運行結果:

很顯然,static靜態(tài)代碼塊并沒有執(zhí)行,我們new 的String類仍是系統(tǒng)包下的String類。
案例解析:
這便是雙親委派機制的完美體現(xiàn)。很好保證了我們系統(tǒng)核心API不容易被破壞。
當我們new String時,我們自己創(chuàng)建的String類應當由系統(tǒng)類加載器(應用程序類加載器)來加載,但根據(jù)雙親委派機制,系統(tǒng)類加載器會先委托給它的父類加載器(拓展類加載器)去加載,如果拓展類加載器仍存在父類則繼續(xù)向上委托。
我們 new String時向上委托會被引導類加載器(BootStap ClassLoader)所加載,所以我們new 出的String便是我們核心API中的String類,即不會再new我們自己創(chuàng)建的String類。
雙親委派機制的優(yōu)勢:
1)避免類的重復加載
2)保護程序安全,防止核心API被隨意篡改
