基礎概念
Classloader 類加載器,用來加載 Java 類到 Java 虛擬機中。與普通程序不同的是。Java程序(class文件)并不是本地的可執行程序。當運行Java程序時,首先運行JVM(Java虛擬機),然后再把Java class加載到JVM里頭運行,負責加載Java class的這部分就叫做Class Loader。
JVM本身包含了一個ClassLoader稱為Bootstrap ClassLoader,和JVM一樣,BootstrapClassLoader是用本地代碼實現的,它負責加載核心JavaClass(即所有java.*開頭的類)。另外JVM還會提供兩個ClassLoader,它們都是用Java語言編寫的,由BootstrapClassLoader加載;其中Extension ClassLoader負責加載擴展的Javaclass(例如所有javax.*開頭的類和存放在JRE的ext目錄下的類),ApplicationClassLoader負責加載應用程序自身的類。
當運行一個程序的時候,JVM啟動,運行bootstrapclassloader,該ClassLoader加載java核心API(ExtClassLoader和AppClassLoader也在此時被加載),然后調用ExtClassLoader加載擴展API,最后AppClassLoader加載CLASSPATH目錄下定義的Class,這就是一個程序最基本的加載流程。
注: 學ClassLoader看OSGI程序應用
什么時候JVM會使用ClassLoader加載一個類呢?當你使用java去執行一個類,JVM使用ApplicationClassLoader加載這個類;然后如果類A引用了類B,不管是直接引用還是用Class.forName()引用,JVM就會找到加載類A的ClassLoader,并用這個ClassLoader來加載類B。JVM按照運行時的有效執行語句,來決定是否需要裝載新類,從而裝載盡可能少的類,這一點和編譯類是不相同的。
Why use your own ClassLoader?
似乎JVM自身的ClassLoader已經足夠了,為什么我們還需要創建自己的ClassLoader呢?
因為JVM自帶的ClassLoader只是懂得從本地文件系統加載標準的java class文件,如果編寫你自己的ClassLoader,你可以做到:
1)在執行非置信代碼之前,自動驗證數字簽名
2)動態地創建符合用戶特定需要的定制化構建類
3)從特定的場所取得java class,例如數據庫中
4) 等等
事實上當使用Applet的時候,就用到了特定的ClassLoader,因為這時需要從網絡上加載java class,并且要檢查相關的安全信息。
應用服務器大都使用了ClassLoader技術,即使你不需要創建自己的ClassLoader,了解其原理也有助于更好地部署自己的應用。
重點注明:其實一個已經加載的類是無法被更新的,如果你試圖用同一個ClassLoader再次加載同一個類,就會得到異常(java.lang.LinkageError: duplicate classdefinition),我們只能夠重新創建一個新的ClassLoader實例來再次加載新類。至于原來已經加載的類,開發人員不必去管它,因為它可能還有實例正在被使用,只要相關的實例都被內存回收了,那么JVM就會在適當的時候把不會再使用的類卸載。
絕大部分Java程序都會使用3種系統提供的類加載器
1.啟動類加載器(Bootstrap ClassLoader),負責將存在<JAVA_HOME>\lib目錄中的,或被-Xbootclasspath參數所指定的路徑中的,并且是虛擬機識別的類庫加載到虛擬機里.注意是按照文件名識別,如rt.jar,名字不符合的類庫即使放在lib目錄中也不會被加載。
2.擴展類加載器(ExtClassLoader),它負責<JAVA_HOME>\lib\ext目錄中的,或被java.ext.dirs系統變量所指定的路徑中的所有類庫.
3.應用程序類加載器(App-ClassLoader),通過cassLoader.getSystemClassLoader()獲取,它負責加載用戶類路徑(ClassPath)上所指定的類庫,一般情況下這個是程序中默認的類加載器.
雙親委托模式 是Java設計者推薦給開發者的一種類加載實現方式.雙親委托模型的工作過程是:如果一個類加載器收到了類加載請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成.每一層次的類加載器都是如此,因此所有的加載請求最終都會傳送到頂層的啟動類加載器中,只有當父類加載器沒有找到所需的類時,子加載器才會嘗試自己去加載。雙親模式的好處是Java類隨著它的類加載器一起具備了一種帶優先級的層次關系。例如類Object,存放在rt.jar中,無論哪個類加載器加載這個類,最終都是委派給處于模型最頂端的啟動類加載,因此Object類在程序使用多種類加載器環境中依然能保證是同一個類。相反,如果沒有使用雙親模型,就可能出現用戶自己編寫一個Object類,導致系統中出現多個不同的Object類,這樣Java類型體系中最基礎的行為也就無法保證。
以上這篇classloader類加載器_基于java類的加載方式詳解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/xiaopihai86/article/details/50767824