類加載相關文章索引:
一文淺析Java中類加載過程
一文弄懂Java中類加載器的關係
Java中自定義類加載器
又是熱愛學習的一天!
雙親委派模型(Parents Delegation Model)
在上一篇文章中(Java中類加載器的關係)我們瞭解到,應用程序都是由3種類加載器相互配合工作的。如果有要求,還可以加上自定義類加載器。而這些類加載器之間的關係如下圖所示:
圖中展示的類加載器之間的這種層次關係,有個專業的名稱,叫做:雙親委派模型(Parents Delegation Model)。雙親委派模型要求除了頂層的啓動類加載器(Bootstrap ClassLoader)外,其他的類加載器都應該有自己的父類加載器。
在上文中已經解釋了 Application ClassLoader、Extension ClassLoader 和 Bootstrap ClassLoader 的關係。而自定義的類加載器的父加載器就是 Application ClassLoader。
雙親委派的機制定義
如果一個類加載器收到了類加載的請求,它首先不會自己嘗試去加載這類,而是把這個請求委派給父加載器去嘗試加載,每一層級的類加載器都是如此。因爲所有的加載請求都應該委派到頂層的啓動類加載器中,只有當父加載器反饋自己無法完成這個加載請求時,子類加載器纔會去嘗試加載。
有這樣的規則是爲了保護我們程序的安全。
雙親外派機制的好處
使用雙親委派模型來組織類加載器之間的關係,有一個明顯的好處就是Java類隨着它的類加載器一起具備了一種帶有優先級的層次關係。這樣就能保證一個類在虛擬機裏的唯一性。
如果我們沒有使用雙親委派機制來進行類加載動作,用戶自己創建了一個叫做 java.lang.Object 的類,並放在程序的 classpath 中,那系統就會有多個不同的 Object 類。那麼Java體系中最基礎的行爲也就無法得到保障。
雙親委派模型的實現原理
雙親委派模型的實現非常簡單,實現雙親委派模型的代碼都集中在 java.lang.ClassLoader 的 loadClass() 方法之中。邏輯清晰易懂,大體流程就是:
- 首先檢查這個類是否已經被加載過了(是否在虛擬機中已經存在了),若已經加載了,就直接進返回。
- 若沒有加載,則調用父類加載器的 loadClass() 方法去嘗試加載。
- 如父類加載器爲空,則使用啓動類加載器去嘗試加載。
- 如果父類加載器加載失敗,則拋出 ClassNotFoundException 異常後,使用自己的 findClass() 方法進行加載。
碼解
下面是 loadClass() 方法的源碼,整個雙親委派模型的實現都在這個方法中體現出來了:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先,檢查請求的類是否已經被加載過了。
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 如果父類不爲空,則調用父類加載器的 loadClass() 方法進行加載。
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 如果父類爲空,則使用啓動類加載器去嘗試加載。
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// 如果父類加載器拋出 ClassNotFoundException
// 說明父加載器無法完成加載請求
}
if (c == null) {
// 在父類加載器無法加載的時候
// 調用自己的 findClass() 方法進行類加載
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;
}
}
如果代碼還不夠清楚的話,下面將使用圖的形式來進行說明:
圖示
雙親委派機制的圖示如下:
明白了雙親委派機制之後,我們就可以自定義類加載器來玩出一些花兒來了。
技 術 無 他, 唯 有 熟 爾。
知 其 然, 也 知 其 所 以 然。
踏 實 一 些, 不 要 着 急, 你 想 要 的 歲 月 都 會 給 你。