共計 2391 個字符,預計需要花費 6 分鐘才能閱讀完成。
這篇文章主要講解了“Java 的雙親委派模型是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“Java 的雙親委派模型是什么”吧!
雙親委派模型的工作流程是:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把請求委托給父加載器去完成,依次向上,因此,所有的類加載請求最終都應該被傳遞到頂層的啟動類加載器中,只有當父加載器在它的搜索范圍中沒有找到所需的類時,即無法完成該加載,子加載器才會嘗試自己去加載該類。
雙親委派機制:
1、當 AppClassLoader 加載一個 class 時,它首先不會自己去嘗試加載這個類,而是把類加載請求委派給父類加載器 ExtClassLoader 去完成。
2、當 ExtClassLoader 加載一個 class 時,它首先也不會自己去嘗試加載這個類,而是把類加載請求委派給 BootStrapClassLoader“` 去完成。
3、如果 BootStrapClassLoader 加載失敗(例如在 $JAVA_HOME/jre/lib 里未查找到該 class),會使用 ExtClassLoader 來嘗試加載;
4、若 ExtClassLoader 也加載失敗,則會使用 AppClassLoader 來加載,如果 AppClassLoader 也加載失敗,則會報出異常 ClassNotFoundException。
ClassLoader 源碼分析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public Class ? loadClass(String name)throws ClassNotFoundException {
return loadClass(name, false);
}
protected synchronized Class ? loadClass(String name, boolean resolve)throws ClassNotFoundException {
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
雙親委派模型意義:
系統類防止內存中出現多份同樣的字節碼
保證 Java 程序安全穩定運行
什么是雙親委派模型?
簡單說,類加載器就是根據指定全限定名稱將 class 文件加載到 JVM 內存,轉為 Class 對象。如果站在 JVM 的角度來看,只存在兩種類加載器:
啟動類加載器(Bootstrap ClassLoader):由 C ++ 語言實現(針對 HotSpot), 負責將存放在 JAVA_HOME \lib 目錄或 -Xbootclasspath 參數指定的路徑中的類庫加載到內存中。
其他類加載器:由 Java 語言實現,繼承自抽象類 ClassLoader。如:擴展類加載器(Extension ClassLoader):負責加載 JAVA_HOME \lib\ext 目錄或 java.ext.dirs 系統變量指定的路徑中的所有類庫。應用程序類加載器(Application ClassLoader)。負責加載用戶類路徑(classpath)上的指定類庫,我們可以直接使用這個類加載器。一般情況,如果我們沒有自定義類加載器默認就是用這個加載器。
雙親委派模型工作過程
雙親委派模型工作過程是:如果一個類加載器收到類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器完成。每個類加載器都是如此,只有當父加載器在自己的搜索范圍內找不到指定的類時(即 ClassNotFoundException),子加載器才會嘗試自己去加載。
為什么需要雙親委派模型?
為什么需要雙親委派模型呢?假設沒有雙親委派模型,試想一個場景:
黑客自定義一個 java.lang.String 類,該 String 類具有系統的 String 類一樣的功能,只是在某個函數稍作修改。比如 equals 函數,這個函數經常使用,如果在這這個函數中,黑客加入一些“病毒代碼”。并且通過自定義類加載器加入到 JVM 中。此時,如果沒有雙親委派模型,那么 JVM 就可能誤以為黑客自定義的 java.lang.String 類是系統的 String 類,導致“病毒代碼”被執行。
而有了雙親委派模型,黑客自定義的 java.lang.String 類永遠都不會被加載進內存。因為首先是最頂端的類加載器加載系統的 java.lang.String 類,最終自定義的類加載器無法加載 java.lang.String 類。
或許你會想,我在自定義的類加載器里面強制加載自定義的 java.lang.String 類,不去通過調用父加載器不就好了嗎? 確實,這樣是可行。但是,在 JVM 中,判斷一個對象是否是某個類型時,如果該對象的實際類型與待比較的類型的類加載器不同,那么會返回 false。
舉個簡單例子:
ClassLoader1、ClassLoader2 都加載 java.lang.String 類,對應 Class1、Class2 對象。那么 Class1 對象不屬于 ClassLoad2 對象加載的 java.lang.String 類型。
感謝各位的閱讀,以上就是“Java 的雙親委派模型是什么”的內容了,經過本文的學習后,相信大家對 Java 的雙親委派模型是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!