淺談一下Java的雙親委派模式
說起雙親委派模型,不得不說一下類加載器。
類加載器是什么?
當(dāng)我們編譯Java類時,JVM會創(chuàng)建與平臺和機器無關(guān)的字節(jié)碼。字節(jié)碼存儲在.class
文件中。當(dāng)我們嘗試使用一個類時,類加載器就會把它加載到內(nèi)存中,然后把字節(jié)碼文件轉(zhuǎn)成Class對象。通俗的說類加載器就是將.class
文件轉(zhuǎn)成Class對象的。
類加載器分類
啟動類加載器(Bootstrap Class Loader):負責(zé)加載存放在 <JAVA_HOME>\lib
目錄下的類,或者被-Xbootclasspath
參數(shù)所指定的路徑中存放的類。比如:rt.jar
、java.lang.*
包下的類。
擴展類加載器(Extension Class Loader):負責(zé)加載<JAVA_HOME>\lib\ext
目錄中,或者被java.ext.dirs
系統(tǒng)變量所指定的路徑中所有的類庫。
應(yīng)用程序類加載器(Application Class Loader):負責(zé)加載用戶類路徑上所有的類庫。
雙親委派模型工作流程
當(dāng)類加載器收到加載類的請求時,它首先會把請求委派給父加載器去完成,每一層都如此,直到把請求委派給最頂層的啟動類加載器,只有當(dāng)父加載器無法加載委派過來的類時,子加載器才會加載。
JVM在加載?個類時,會調(diào)?AppClassLoader的loadClass
?法來加載這個類,不過在這個?法中,會先使?ExtClassLoader的loadClass
?法來加載類,同樣ExtClassLoader的loadClass
?法中會先使?BootstrapClassLoader來加載類,如果BootstrapClassLoader加載到了就直接成功,如果 BootstrapClassLoader沒有加載到,那么ExtClassLoader就會??嘗試加載該類,如果沒有加載到,那么則會由AppClassLoader來加載這個類。
所以,雙親委派指得是,JVM在加載類時,會委派給ExtClassLoader和BootstrapClassLoader進?加載,如果沒加載到才由??進?加載。
這里說的雙親并不是說類加載器之間是以繼承方式實現(xiàn)的,而是以組合的方式實現(xiàn)的,通過源碼可以證實這點:
java.lang.ClassLoader#loadClass
private final ClassLoader parent; protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
同時,通過源碼我們也可以看到類加載器的加載流程是跟我們描述的一樣的:先檢查請求加載的類型是否已經(jīng)被加載過,若沒有則調(diào)用父加載器的loadClass()
方法,若父加載器為空則默認(rèn)使用啟動類加載器作為父加載器。假如父類加載器加載失敗,拋出ClassNotFoundException
異常的話,才調(diào)用自己的findClass()
方法嘗試進行加載。
雙親委派模型好處
保證唯一性,避免重復(fù)加載:類的加載隨著它的類加載器一起具備了層級關(guān)系,通過這種層級關(guān)系避免了重復(fù)加載,父類加載器加載了該類,子加載器就無需加載了。
避免核心類被篡改:核心類由啟動類加載器加載,即使用戶自定義同名核心類也不會被加載。
到此這篇關(guān)于淺談一下Java的雙親委派模式的文章就介紹到這了,更多相關(guān)java雙親委派模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Maven Plugin的@Mojo和@Execute的具體使用
本文主要介紹了Maven Plugin的@Mojo和@Execute的具體使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09JavaWeb中struts2實現(xiàn)文件上傳下載功能實例解析
這篇文章主要介紹了JavaWeb中struts2文件上傳下載功能的實現(xiàn),在Web應(yīng)用系統(tǒng)開發(fā)中,文件上傳和下載功能是非常常用的功能,需要的朋友可以參考下2016-05-05微信小程序獲取手機號的完整實例(Java后臺實現(xiàn))
我們在做小程序開發(fā)的過程中,經(jīng)常會涉及到用戶身份的問題,最普遍的就是我們要獲取用戶的手機號碼,下面這篇文章主要給大家介紹了關(guān)于微信小程序獲取手機號的完整實例,后臺由Java實現(xiàn),需要的朋友可以參考下2022-06-06java基于數(shù)據(jù)庫實現(xiàn)全局唯一ID的示例
本文主要介紹了java基于數(shù)據(jù)庫實現(xiàn)全局唯一ID的示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04詳解Spring Security的formLogin登錄認(rèn)證模式
對于一個完整的應(yīng)用系統(tǒng),與登錄驗證相關(guān)的頁面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁面,也就是本文給大家介紹的formLogin模式登錄認(rèn)證模式,感興趣的朋友跟隨小編一起看看吧2019-11-11沒有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項目的?
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著在沒有編輯器的環(huán)境下如何創(chuàng)建Servlet(Tomcat+Java)項目展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06