1. 程式人生 > >深入理解雙親委託機制

深入理解雙親委託機制

JVM設計者把類載入階段中的“通過'類全名'來獲取定義此類的二進位制位元組流”這個動作放到Java虛擬機器外部去實現,以便讓應用程式自己決定如何去獲取所需要的類。實現這個動作的程式碼模組稱為“類載入器”。


1.類與類載入器

對於任何一個類,都需要由載入它的類載入器和這個類來確立其在JVM中的唯一性。也就是說,兩個類來源於同一個Class檔案,並且被同一個類載入器載入,這兩個類才相等。

2.雙親委派模型

從虛擬機器的角度來說,只存在兩種不同的類載入器:一種是啟動類載入器(Bootstrap ClassLoader),該類載入器使用C++語言實現,屬於虛擬機器自身的一部分。另外一種就是所有其它的類載入器,這些類載入器是由Java語言實現,獨立於JVM外部,並且全部繼承自抽象類java.lang.ClassLoader。


JDK 預設提供瞭如下幾種ClassLoader

1.  Bootstrp loader

Bootstrp載入器是用C++語言寫的,它是在Java虛擬機器啟動後初始化的,它主要負責載入%JAVA_HOME%/jre/lib,-Xbootclasspath引數指定的路徑以及%JAVA_HOME%/jre/classes中的類。rt.jar

 

2.  ExtClassLoader  

Bootstrploader載入ExtClassLoader,並且將ExtClassLoader的父載入器設定為Bootstrploader,

ExtClassLoader是用Java寫的,具體來說就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要載入%JAVA_HOME%/jre/lib/ext,此路徑下的所有classes目錄以及java.ext.dirs系統變數指定的路徑中類庫。

3.  AppClassLoader

Bootstrploader載入完ExtClassLoader後,就會載入AppClassLoader,並且將AppClassLoader的父載入器指定為ExtClassLoader。AppClassLoader也是用Java寫成的,它的實現類是sun.misc.Launcher$AppClassLoader,另外我們知道ClassLoader中有個getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要負責載入classpath所指定的位置的類或者是jar文件,它也是Java程式預設的類載入器。


雙親委派機制的工作流程:

1. 當前ClassLoader首先從自己已經載入的類中查詢是否此類已經載入,如果已經載入則直接返回原來已經載入的類。

每個類載入器都有自己的載入快取,當一個類被載入了以後就會放入快取,等下次載入的時候就可以直接返回了。

2.  當前classLoader的快取中沒有找到被載入的類的時候,委託父類載入器去載入,父類載入器採用同樣的策略,首先檢視自己的快取,然後委託父類的父類去載入,一直到bootstrp ClassLoader.

3.  當所有的父類載入器都沒有載入的時候,再由當前的類載入器載入,並將其放入它自己的快取中,以便下次有載入請求的時候直接返回。


總結:

“雙親委派”機制只是Java推薦的機制,並不是強制的機制。

我們可以繼承java.lang.ClassLoader類,實現自己的類載入器。如果想保持雙親委派模型,就應該重寫findClass(name)方法;如果想破壞雙親委派模型,可以重寫loadClass(name)方法。具體細節建議看下原始碼