JAVA類裝載方式,有兩種:
隱式裝載, 程序在運行過程當中當碰到經過new 等方式生成對象時,隱式調用類裝載器加載對應的類到jvm中。
顯式裝載, 經過class.forname()等方法,顯式加載須要的類html
類加載的動態性體現:java
一個應用程序老是由n多個類組成,Java程序啓動時,並非一次把全部的類所有加載後再運行,它老是先把保證程序運行的基礎類一次性加載到jvm中,其它類等到jvm用到的時候再加載,這樣的好處是節省了內存的開銷,由於java最先就是爲嵌入式系統而設計的,內存寶貴,這是一種能夠理解的機制,而用到時再加載這也是java動態性的一種體現。 JDK 默認提供了以下幾種ClassLoader
Bootstrp loaderjvm
Bootstrp加載器是用C++語言寫的,它是在Java虛擬機啓動後初始化的,它主要負責加載%JAVA_HOME%/jre/lib,-Xbootclasspath參數指定的路徑以及%JAVA_HOME%/jre/classes中的類。
ExtClassLoaderspa
Bootstrp loader加載ExtClassLoader,而且將ExtClassLoader的父加載器設置爲Bootstrp loader.ExtClassLoader是用Java寫的,具體來講就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要加載%JAVA_HOME%/jre/lib/ext,此路徑下的全部classes目錄以及java.ext.dirs系統變量指定的路徑中類庫。
AppClassLoader設計
Bootstrp loader加載完ExtClassLoader後,就會加載AppClassLoader,而且將AppClassLoader的父加載器指定爲 ExtClassLoader。AppClassLoader也是用Java寫成的,它的實現類是 sun.misc.Launcher$AppClassLoader,另外咱們知道ClassLoader中有個getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要負責加載classpath所指定的位置的類或者是jar文檔,它也是Java程序默認的類加載器。 綜上所述,它們之間的關係能夠經過下圖形象的描述: 爲何要有三個類加載器,一方面是分工,各自負責各自的區塊,另外一方面爲了實現委託模型。
類加載器之間是如何協調工做的code
前面說了,java中有三個類加載器,問題就來了,碰到一個類須要加載時,它們之間是如何協調工做的,即java是如何區分一個類該由哪一個類加載器來完成呢。 在這裏java採用了委託模型機制,這個機制簡單來說,就是「類裝載器有載入類的需求時,會先請示其Parent使用其搜索路徑幫忙載入,若是Parent 找不到,那麼才由本身依照本身的搜索路徑搜索類」 下面舉一個例子來講明,爲了更好的理解,先弄清楚幾行代碼:
[Java] 純文本查看 複製代碼
?htm
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);
}blog
}內存
運行結果:
[Java] 純文本查看 複製代碼
?
……AppClassLoader……
……ExtClassLoader……
Null
能夠看出Test是由AppClassLoader加載器加載的,AppClassLoader的Parent 加載器是 ExtClassLoader,可是ExtClassLoader的Parent爲 null 是怎麼回事呵,朋友們留意的話,前面有提到Bootstrap Loader是用C++語言寫的,依java的觀點來看,邏輯上並不存在Bootstrap Loader的類實體,因此在java程序代碼裏試圖打印出其內容時,咱們就會看到輸出爲null。
注:本文轉自博客園,版權歸博客園全部。
原文連接:https://www.cnblogs.com/doit8791/p/5820037.html