JVM面試(一) java虛擬機器器:雙親委派機制 的工作原理

2020-10-29 11:00:26

類的載入:

載入指的是將類的class檔案讀入到記憶體,併為之建立一個java.lang.Class物件,也就是說,當程式中使用任何類時,系統都會為之建立一個java.lang.Class物件。
類的載入由類載入器完成,類載入器通常由JVM提供,這些類載入器也是前面所有程式執行的基礎,JVM提供的這些類載入器通常被稱為系統類載入器。除此之外,開發者可以通過繼承ClassLoader基礎類別來建立自己的類載入器。

雙親委派機制 的工作原理

1)如果一個類載入器收到了類載入請求,它並不會自己先去載入,而是把這個請求委託給父類別的載入器去執行。
2)如果父類別載入器還存在其父類別載入器,則進一步向上委託,依次遞迴請求最終將到達頂層的啟動類載入器。
3)如果父類別載入器可以完成類載入任務,就成功返回,倘若父類別載入器無法完成此載入任務,子載入器才會嘗試自己去載入,這就是雙親委派模式。
在這裡插入圖片描述

案例舉例:

下面我們不妨通過一個例子來幫助我們理解一下雙親委派機制:
首先我們在工程下建立一個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系統包下的String呢還是我們剛剛自己定義的String類呢?
換言之,我們在上面定義的String類中加入的static靜態程式碼塊會不會執行呢??
請看執行結果:
在這裡插入圖片描述
很顯然,static靜態程式碼塊並沒有執行,我們new 的String類仍是系統包下的String類。

案例解析:

這便是雙親委派機制的完美體現。很好保證了我們系統核心API不容易被破壞。
當我們new String時,我們自己建立的String類應當由系統類載入器(應用程式類載入器)來載入,但根據雙親委派機制,系統類載入器會先委託給它的父類別載入器(拓展類載入器)去載入,如果拓展類載入器仍存在父類別則繼續向上委託。
我們 new String時向上委託會被引導類載入器(BootStap ClassLoader)所載入,所以我們new 出的String便是我們核心API中的String類,即不會再new我們自己建立的String類。

雙親委派機制的優勢:

1)避免類的重複載入
2)保護程式安全,防止核心API被隨意篡改