1.java類載入器?
Java類載入器ClassLoader總結
JAVA類裝載方式,有兩種:
1.隱式裝載, 程式在執行過程中當碰到通過new 等方式生成物件時,隱式呼叫類裝載器載入對應的類到jvm中。
2.顯式裝載, 通過class.forname()等方法,顯式載入需要的類
類載入的動態性體現:
一個應用程式總是由n多個類組成,Java程式啟動時,並不是一次把所有的類全部載入後再執行,它總是先把保證程式執行的基礎類一次性載入到jvm中,其它類等到jvm用到的時候再載入,這樣的好處是節省了記憶體的開銷,因為java最早就是為嵌入式系統而設計的,記憶體寶貴,這是一種可以理解的機制,而用到時再載入這也是java動態性的一種體現
java類裝載器
JDK 預設提供瞭如下幾種ClassLoader
-
Bootstrp loader
Bootstrp載入器是用C++語言寫的,它是在Java虛擬機器啟動後初始化的,它主要負責載入%JAVA_HOME%/jre/lib
,-Xbootclasspath
引數指定的路徑以及%JAVA_HOME%/jre/classes
中的類。
-
ExtClassLoader
Bootstrp loader載入ExtClassLoader,並且將ExtClassLoader的父載入器設定為Bootstrp loader.ExtClassLoader是用Java寫的,具體來說就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要載入%JAVA_HOME%/jre/lib/ext
java.ext.dirs
系統變數指定的路徑中類庫。 -
AppClassLoader
Bootstrp loader載入完ExtClassLoader後,就會載入AppClassLoader,並且將AppClassLoader的父載入器指定為 ExtClassLoader。AppClassLoader也是用Java寫成的,它的實現類是 sun.misc.Launcher$AppClassLoader,另外我們知道ClassLoader中有個getSystemClassLoader
方法,此方法返回的正是AppclassLoader.AppClassLoader主要負責載入classpath所指定的位置的類或者是jar文件,它也是Java程式預設的類載入器。
綜上所述,它們之間的關係可以通過下圖形象的描述:
為什麼要有三個類載入器,一方面是分工,各自負責各自的區塊,另一方面為了實現委託模型。
類載入器之間是如何協調工作的
前面說了,java中有三個類載入器,問題就來了,碰到一個類需要載入時,它們之間是如何協調工作的,即java是如何區分一個類該由哪個類載入器來完成呢。 在這裡java採用了委託模型機制,這個機制簡單來講,就是“類裝載器有載入類的需求時,會先請示其Parent使用其搜尋路徑幫忙載入,如果Parent 找不到,那麼才由自己依照自己的搜尋路徑搜尋類”
下面舉一個例子來說明,為了更好的理解,先弄清楚幾行程式碼:
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Public class Test{
Public static void main(String[] arg){
ClassLoader c = Test.class.getClassLoader(); //獲取Test類的類載入器
System.out.println(c);
ClassLoader c1 = c.getParent(); //獲取c這個類載入器的父類載入器
System.out.println(c1);
ClassLoader c2 = c1.getParent();//獲取c1這個類載入器的父類載入器
System.out.println(c2);
}
} |
執行結果:
Java
1 2 3 4 5 |
……AppClassLoader……
……ExtClassLoader……
Null |
可以看出Test是由AppClassLoader載入器載入的,AppClassLoader的Parent
載入器是 ExtClassLoader,但是ExtClassLoader
的Parent
為 null
是怎麼回事呵,朋友們留意的話,前面有提到Bootstrap Loader是用C++語言寫的,依java的觀點來看,邏輯上並不存在Bootstrap Loader的類實體,所以在java
程式程式碼裡試圖打印出其內容時,我們就會看到輸出為null
。