[五]類加載機制雙親委派機制 底層代碼實現原理 源碼分析 java類加載雙親委派機制是如何實現的

 

Launcher啓動類


本文是雙親委派機制的源碼分析部分,類加載機制中的雙親委派模型對於jvm的穩定運行是很是重要的
不過源碼其實比較簡單,接下來簡單介紹一下
 
咱們先從啓動類提及
有一個Launcher類   sun.misc.Launcher;
image_5b8be55e_4272
 
仔細看下這簡短的幾行註釋,能夠獲得有用的信息
ps:直接IDE裏面查看反編譯的,看不到註釋的,能夠下載openJDK查看源碼,個人這個版本是openjdk-8-src-b132-03_mar_2014
 
sun.misc.Launcher
這個類是系統用於啓動主應用的啓動器
 
構造方法 Launcher() 中作了四件事情
建立          擴展          類加載器
建立          應用程序    類加載器
設置ContextClassLoader
若是須要安裝安全管理器 security manager
其中launcher是staitc的,因此初始化的時候就會建立對象,也就是觸發了構造方法,因此初始化的時候就會執行上面四個步驟
image_5b8be55e_3add
 
ExtClassLoader 和  AppClassLoader  都是Launcher的靜態內部類
image_5b8be55e_6921
並且,他們也都是ClassLoader的實現類
image_5b8be55e_3cb7
 
看下ExtClassLoader的建立中的關鍵幾步
image_5b8be55e_77fe
 
也在看下AppClassLoader的建立中的關鍵幾步
image_5b8be55e_7080
 
另外還有
Launcher類中的靜態變量
image_5b8be55e_62a5
 
你應該能夠想獲得下面這三個究竟是什麼東西,若是真不懂,你須要再去研究下
System.getProperty("sun.boot.class.path")
System.getProperty("java.ext.dirs")
System.getProperty("java.class.path")
 
 
 

ClassLoader的構造方法

 
 
前面說過,對於虛擬機來講只有兩種類加載器
啓動類加載器以及其餘全部,而其餘全部都是java.lang.ClassLoader的子類
因此想要自定義類加載器,必需要繼承實現ClassLoader
並且,咱們上面說到的,java給咱們提供的AppClassLoader 和 ExtClassLoader 也都是ClassLoader的子類
 
看下ClassLoader的構造方法 和變量parent
你會發現,其實構造方法實際上只有雙參數版本這一種
第二個參數爲parent,這個parent是一個ClassLoader,  用於記錄他的  父    類加載器
 
無論調用哪一個構造方法
parent必然會被初始化
要麼是你調用帶參數的構造方法, 顯式指定一個來設置parent
若是你不指定,默認的構造方法,會使用  getSystemClassLoader返回的AppClassLoader  設置parent
 
 
 
image_5b8be55e_2925
ps:
本文中的很多地方,我都在"父類加載器" 的"父 "和"類加載器"中間加了幾個空格
千萬不要理解成父類加載器  ,<父    類加載器> 指的是類加載器的加載順序層級結構的優先順序   而不是平時說的繼承關係中的父類 父 意味着他的上一層級
 
getSystemClassLoader 獲取AppClassLoader 的過程
image_5b8be55f_2f0b
 
那麼再回頭看一眼  應用程序   類加載器的構造
擴展  類加載器做爲參數傳遞給了他,他最終調用的就是ClassLoader 的一個參數的構造方法  
將ExtClassLoader 設置爲 AppClassLoader  的parent
image_5b8be55f_4098
 
而ExtClassLoader,他的parent 是null
image_5b8be55f_53e0
 
ps:啓動  類加載器 是虛擬機的一部分,可能c/c++/java實現的,因此不是java語言的一部分
因此對於java自己來講,能夠說他是不存在的,可是JVM是知道他的
因此說,此處爲null ,parent爲null說明他的父    類加載器是啓動類加載器   或者可能就是啓動  類加載器自己

loadClass與findClass

想要實現類 加載器,須要繼承ClassLoader
而且有兩個重要的方法
看下兩個重要方法的聲明,你可能就感受出來了,想一想public 和 protected都是啥意思?
image_5b8be55f_6d2f
 
loadClass方法是類加載器執行   加載類邏輯   的方法,包括檢查是否已經加載,調用父類加載,失敗則本身嘗試使用 findClass方法加載
findClass當前類加載器 實際執行加載二進制流的具體行爲方法
 
Launcher.APPClassLoader中的loadClass方法,最終調用的是super.loadClass  , 實際上就是ClassLoader的loadClass方法
Launcher.ExtClassLoader  根本就沒有實現本身的loadClass 方法,因此使用的也是ClassLoader中的
 
image_5b8be55f_66ff
 
再來看看ClassLoader的loadClass方法
他會調用parent的loadClass方法,若是他的parent不爲空,將會一直調用父 類加載器, 直到最頂級的  啓動   類加載器 
若是 啓動   類加載器仍舊找尋不到, 那麼調用自身的findClass 
image_5b8be55f_2ac5
 
若是本身調用findClass加載失敗呢?
很顯然, 函數調用結束以後,會返回到調用點位置,調用棧的形式嘛
也就是通過
image_5b8be55f_1e1a
必然要繼續執行他的下一段
若是沒拋出異常的話,就會走到下面這裏
image_5b8be55f_5b1f
顯然這就完成了一整個的雙親委派的類加載模式
 
image_5b8be55f_4c07
 

總結

Launcher做爲啓動器
建立了ExtClassLoader 以及AppClassLoader
他們都是ClassLoader的子類,而且ClassLoader有一個parent  指向他的父   類加載器
正是這個屬性完成了自頂而下的 優先級層級順序的肯定
對於sun內置的ExtClassLoader 以及AppClassLoader  以及啓動  類加載器 Bootstrap  他們的層級爲
Bootstrap>ExtClassLoader>ExtClassLoader
而且,他們各自有不一樣的分工
經過ClassLoader的loadClass方法,肯定了他們的調用邏輯,也就是雙親委派機制
每一個層級都會向上傳遞類加載請求,只有上層  父     類加載器調用失敗,纔會本身嘗試加載
雙親委派機制的意義重大,帶來了更高的安全性等優勢
不過他的實現邏輯倒是的確很簡單
一個loadClass就搞定了
findClass是類加載器自身加載類的具體行爲
因此,若是你不須要破壞雙親委派機制,只須要覆蓋這個方法便可
若是你想要徹底自定義你的類加載器的邏輯機制,直接覆蓋loadClass,固然,你可能還須要繼續覆蓋findClass
相關文章
相關標籤/搜索