標籤:bootstra already 除了 throw 組合 return 參考 一個 c++實現
Java 類載入器類載入器
類載入器用於載入Java類到虛擬機器中,載入一個Class首先需要擷取該Class的二進位位元組流,這個過程可以通過自訂類載入器(覆蓋findClass方法)來實現,從而可以通過多種靈活的途徑擷取Class的二進位位元組流。
每個類載入器都擁有一個獨立的類名稱空間,一個Class的唯一性需要通過其類載入器確定,判斷兩個Class是否是同一個Class的前提是這兩個Class是由同一個類載入器載入,即使兩個Class來自於同一個Class檔案,若它們被不同的類載入器載入進虛擬機器,也會認為是兩個不同的Class。
類載入器主要包括以下幾種類型:
- 啟動類載入器(Bootstrap ClassLoader)
啟動類載入器用於載入JAVA_HOME\lib目錄中的系統類別庫(如:rt.jar),它是虛擬機器的一部分,使用C++實現。
- 擴充類載入(Extension ClassLoader)
擴充類載入器由sun.misc.Launcher$ExtClassLoader實現,負責載入JAVA_HOME\lib\ext中的所有類庫。
- 應用程式類載入器(Application ClassLoader)
應用程式類載入器由sun.misc.Launcher$AppClassLoader實現,負責載入ClassPath中包含的所有類庫,它是應用程式中使用的預設類載入器,如果不使用自訂的類載入器,則應用程式的所有Class都是由該類載入器載入。
雙親委派模型
各種類載入器之間的關係如所示:
在雙親委派模型中,除了啟動類載入器沒有父類載入器,其他的類載入器都應該有一個父類載入器(並不一定以繼承的方式實現,通常以組合的方式去實現)。
一個類載入器去載入一個Class時,會首先委派其父類載入器去載入,只有父類載入器無法載入時,才會自己去載入。因此所有的類載入請求都會先經過啟動類載入器。
雙親委派模型的代碼實現在java.lang.ClassLoader的loadClass方法之中:
protected synchronized Class<?> loadClass (String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { 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. c = findClass(name); } } if (resolve) { resolveClass(c); } return c;}
(1)判斷Class是否已經被載入過
(2)如果沒有被載入,則交給父類載入器去載入,如果沒有指定父類載入器(父類載入器為null),則交由啟動類載入器去載入。
(3)經過上述兩步仍然無法載入,則調用自己的findClass方法載入
雙親委派模型可以保證重要的系統Class始終由啟動類載入器載入,確保Java運行環境的穩定性和正確性。
參考資料:《深入理解Java虛擬機器》
Java 類載入器