雙親委派機制,是jvm類加載中重要的安全機制。
java虛擬機對class文件採用的是按需加載的方式,也就是說需要使用該類時才會將它的class文件加載到內存生成class對象。而且加載某個類的class文件時,java虛擬機採用的是雙親委派模式,即把請求交給父類處理,它是一種任務委派模式。
首先看一個問題:以下代碼是否會調用我們自己定義的String類
<code>package java.lang;
public class String {
//如果新創建的對象是我們自定義的String,該靜態代碼塊會執行
//控制檯上會打印“自定義的String”
static{
System.out.println("自定義的String");
}
}
package test;
public class StringTest {
public static void main(String[] args) {
String str=new String();
System.out.println("hello");
}
}/<code>
出現的問題:
jdk自帶了java.lang.String,我們也創建了一個java.lang.String,那麼新創建的對象String會是誰的對象呢?
驗證思路:
在我們自定義的String中,添加了靜態代碼塊,如果創建對象,一定會執行打印語句。jdk自帶的java.lang.String在新創建過程中並不會打印任何東西。所以我們只要看控制檯是否有輸出即可,若打印出“自定義的String”,則創建了我們自定義的String,若沒有打印信息,則創建了jdk自帶的String。
並沒有打印出“自定義的String‘,所以可以得出結論新創建對象時,jvm加載了自帶的String。
此過程中,就使用到了雙親委派機制。
那麼雙親委派機制如何工作的呢?
工作原理
1.如果一個類加載器收到了類加載請求,它並不會自己先去加載,而是先把這個加載任務交給他的父類。
2.如果父類加載器還存在父類,那麼就繼續向上委託任務。
3.如果父類加載器可以完成,父類就去做這個任務,併成功返回;若父類加載器無法完成此加載任務,子類加載器才會嘗試自己去加載
類比上邊的例子
1.當jvm看到String str=new String()時,此時jvm會根據java.lang.String從磁盤中找該類
2.若 系統類加載器 接收到此任務,它會交給它的父類擴展類加載器
3.擴展類加載器 接到此任務,它把這個任務交給引導類加載器
4.引導類加載器 沒有父類了,所以它嘗試加載這個java.lange.String,他從JAVA_HOME/jre/lib/rt.jar、resources.jar找到了這個類,就將其加載返回
5.所以並不會加載我們自定義的String
再舉個生活中的例子
幼兒園小朋友學過孔融讓梨,一天得到一個蘋果,小朋友把蘋果給父母吃,父母又把蘋果給了爺爺奶奶。如果爺爺奶奶吃了,小朋友就沒有蘋果吃了。如果父母把蘋果吃了,小朋友也沒有蘋果吃了。如果爺爺奶奶、父母都不吃,小朋友就可以開心地吃蘋果了。
總結:
類加載器接收到任務,先把任務交給父類,如果父類還有父類,接著向上遞交任務(也可以說委託任務),直到最頂層的類加載器,才開始嘗試處理加載任務,如果處理不了再交給子類處理。
結尾:如果有什麼疑問,可以在下方評論,我會一一作答
閱讀更多 嘿嘿哎四個窩窩頭 的文章