三種系統提供的類加載器:
- 啓動類加載器(Bootstrap):這個類加載器負責將放在JAVA_HOME/lib目錄下的類庫記載到虛擬機內存中,這個加載器無法被程序引用
- 擴展類加載器(Extension):由sun.misc.Launcher$ExtClassLoader實現,負責加載JAVA_HOME/lib/ext目錄或者java.ext.dirs指定的路徑的類庫
- 應用程序類加載器(Application):由sun.misc.Launcher$AppClassLoader實現,負責加載用戶類路徑上指定的類庫(CLASSPATH指定的類庫),一般情況下這個就是程序中默認的類加載器
加載路徑簡單描述:
BootStrap –>JRE/lib/rt.jar
ExtClassLoader–>JRE/lib/ext/*.jar
AppClassLoader–>CLASSPATH指定的所有jar或目錄
(配置環境變量,讓AppClassLoader這個類加載器能去加載我們寫的類)
雙親委派模型
如果一個類加載器收到了類加載的請求,首先不會自己去嘗試加載這個類,而是把請求委派給父類加載器去完成,如果父類加載器無法無法完成這個加載請求,子類加載器纔會嘗試自己去加載,這是推薦的類加載器模型
問題:能不能自己寫一個類加載java.lang.System?
回答:類加載採用委託機制,總是保證父類優先與子類,也就是如果父類找到了你委託它加載的類,那麼它直接把加載完的字節碼給你,由於BootStrap(啓動類加載器)可以加載rt.jar下面有System這個類,所以總是由BootStrap來加載System類,而不是用我們自己編寫的類加載器來加載.
代碼例子
/*
* 類加載器有3個: BootStrap,ExtClassLoader,AppClassLoader
*/
System.out.println(test.class.getClassLoader().getClass().getName());
// 打印出AppClassLoader,由AppClassLoader加載的
System.out.println(System.class.getClassLoader());
// 打印出null,由BootStrap加載的
// 測試3個類加載器的父子關係
ClassLoader loader = test.class.getClassLoader();
while(loader !=null) {
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
System.out.println(loader);
/*
* 打印出AppClassLoader----的父類-->ExtClassLoader----的父類-->BootStrap,
* BootStrap是最頂部的類加載
*/