此答案節選自我們最近弄的
面試鴨小程式
,更多
大廠常問面試題
,可以點選下面的小程式進行閱讀哈!
目前這個面試刷題小程式剛出,詳細可以看這篇文章:
回歸面試題!
雙親委派的意思是:如果一個類載入器需要載入類,那麽首先它會把這個類載入請求委派給父類載入器去完成,如果父類還有父類則接著委托,每一層都是如此。一直遞迴到頂層,當父載入器無法完成這個請求時,子類別才會嘗試去載入。
父類也不是我們平日所說的那種繼承關系,只是呼叫邏輯是這樣。
在 JDK 9 之前 ,Java 自身提供了 3 種類載入器:
啟動類載入器(
Bootstrap classLoader
),它是屬於虛擬機器自身的一部份,用 C++ 實作的,主要負責載入<JAVA_HOME>\lib
目錄中或被-Xboot classpath
指定的路徑中的並且檔名是被虛擬機器辨識的檔。它是所有類載入器的爸爸。擴充套件類載入器(
Extension classLoader
),它是 Java 實作的,獨立於虛擬機器,主要負責載入<JAVA_HOME>\lib\ext
目錄中或被java.ext.dirs
系統變量所指定的路徑的類別庫。應用程式類載入器(
Application classLoader
),它是 Java 實作的,獨立於虛擬機器。主要負責載入使用者類路徑(classPath
)上的類別庫,如果我們沒有實作自訂的類載入器那這玩意就是我們程式中的預設載入器。
所以一般情況類載入會從應用程式類載入器委托給擴充套件類再委托給啟動類,啟動類找不到然後擴充套件類找,擴充套件類載入器找不到再應用程式類載入器找。
雙親委派模型不是一種強制性約束,也就是你不這麽做也不會報錯怎樣的, 它是一種JAVA設計者推薦使用類載入器的方式 。
為什麽要有雙親委派機制?
它使得類有了層次的劃分。就拿
java.lang.Object
來說,載入它經過一層層委托最終是由
Bootstrap classLoader
來載入的,也就是最終都是由
Bootstrap classLoader
去找
\lib
中
rt.jar
裏面的
java.lang.Object
載入到
JVM
中。
這樣如果有不法分子自己造了個
java.lang.Object
,裏面嵌了不好的程式碼,如果我們是按照雙親委派模型來實作的話,最終載入到
JVM
中的只會是我們
rt.jar
裏面的東西,也就是這些核心的基礎類程式碼得到了保護。
因為這個機制使得系統中只會出現一個
java.lang.Object
。不會亂套了。你想想如果我們
JVM
裏面有兩個
Object
,那豈不是天下大亂了。
那你知道有違反雙親委派的例子嗎?
典型的例子就是:
JDBC
。
JDBC
的介面是類別庫定義的,但實作是在各大資料庫廠商提供的
jar
包中,那透過啟動類載入器是找不到這個實作類的,所以就需要應用程式載入器去完成這個任務,這就違反了自下而上的委托機制了。
具體做法是搞了個執行緒上下文類載入器,透過
setContext classLoader()
預設設定了應用程式類載入器,然後透過
Thread.current.currentThread().getContext classLoader()
獲得類載入器來載入。
JDK 9 關於類載入器進行了一些修改,詳細可以看面試鴨:【類載入器有了解過嗎?】這題。
最後
最後再推薦下鴨鴨目前努力在做 面試小程式神器 ,如果大家有不會的面試題,也可以在小程式內反饋!鴨鴨會第一時間為大家解答!
網頁版也即將上線! 後續肯定會漲價,現在就是最低價!
我是鴨鴨,我們下期見~