文章摘抄至 http://longdick.iteye.com/blog/442213/
?
要深入了解ClassLoader,首先就要知道ClassLoader是用來干什么的,顧名思義,它就是用來加載Class文件到JVM,以供程序使用的。我們知道,java程序可以動態加載類定義,而這個動態加載的機制就是通過ClassLoader來實現的,所以可想而知ClassLoader的重要性如何。?
?
看到這里,可能有的朋友會想到一個問題,那就是既然ClassLoader是用來加載類到JVM中的,那么ClassLoader又是如何被加載呢?難道它不是java的類??
?
沒有錯,在這里確實有一個ClassLoader不是用java語言所編寫的,而是JVM實現的一部分,這個ClassLoader就是bootstrap classloader(啟動類加載器),這個ClassLoader在JVM運行的時候加載java核心的API以滿足java程序最基本的需求,其中就包括用戶定義的ClassLoader,這里所謂的用戶定義是指通過java程序實現的ClassLoader,一個是ExtClassLoader,這個ClassLoader是用來加載java的擴展API的,也就是/lib/ext中的類,一個是AppClassLoader,這個ClassLoader是用來加載用戶機器上CLASSPATH設置目錄中的Class的,通常在沒有指定ClassLoader的情況下,程序員自定義的類就由該ClassLoader進行加載。?
?
當運行一個程序的時候,JVM啟動,運行bootstrap classloader,該ClassLoader加載java核心API(ExtClassLoader和AppClassLoader也在此時被加載),然后調用ExtClassLoader加載擴展API,最后AppClassLoader加載CLASSPATH目錄下定義的Class,這就是一個程序最基本的加載流程
?
java應用環境中不同的class分別由不同的ClassLoader負責加載。
一個jvm中默認的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分別各司其職:
- Bootstrap ClassLoader?? ?? ?負責加載java基礎類,主要是 %JRE_HOME/lib/ 目錄下的rt.jar、resources.jar、charsets.jar和class等
- Extension ClassLoader?? ? ?? 負責加載java擴展類,主要是 %JRE_HOME/lib/ext 目錄下的jar和class
- App ClassLoader???? ?????? 負責加載當前java應用的classpath中的所有類。
其中Bootstrap ClassLoader是JVM級別的,由C++撰寫;Extension ClassLoader、App ClassLoader都是java類,都繼承自URLClassLoader超類。
Bootstrap ClassLoader由JVM啟動,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。
下圖是ClassLoader的加載類流程圖,以加載一個類的過程類示例說明整個ClassLoader的過程。
public class ClassLoaderTree { public static void main(String[] args) { ClassLoader loader = ClassLoaderTree.class.getClassLoader(); /** sun.misc.Launcher$AppClassLoader@39ab89 系統類加載器 sun.misc.Launcher$ExtClassLoader@2cb49d 擴展類加載器 */ while(loader != null){ System.out.println(loader.toString()); loader = loader.getParent(); } } }
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的關系如下:
Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。但是這并不是繼承關系,只是語義上的定義,基本上,每一個ClassLoader實現,都有一個Parent ClassLoader。
?
可以通過ClassLoader的getParent方法得到當前ClassLoader的parent。Bootstrap ClassLoader比較特殊,因為它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。
?
當使用ClassLoader類的loadClass()方法來加載某個類時,該方法只是加載該類,并不會執行該類的初始化。使用Class的forName()靜態方法才會導致強制初始化該類。
package hb.reflect; public class Tester{ static{ System.out.println("初始化塊"); } }
?
package hb.reflect; public class ClassLoaderTest { public static void main(String[] args) throws ClassNotFoundException { ClassLoader c1 = ClassLoader.getSystemClassLoader(); //不會執行初始化 c1.loadClass("hb.reflect.Tester"); System.out.println("系統加載Tester類"); //執行初始化內容 Class.forName("hb.reflect.Tester"); } }
?打印內容:
系統加載Tester類
初始化塊
?
如果將代碼如下修改:
package hb.classloader; public class ClassLoaderTest { public static void main(String[] args) throws ClassNotFoundException { ClassLoader c1 = ClassLoader.getSystemClassLoader(); //不會執行初始化 Class clazz = c1.loadClass("hb.classloader.Tester"); // try { Tester tester = (Tester)clazz.newInstance(); tester.print("class.newInstance() is ok"); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } System.out.println("系統加載Tester類"); //執行初始化內容 Class.forName("hb.classloader.Tester"); } }
?打印結果:
初始化塊
class.newInstance() is ok
系統加載Tester類
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
