| 加載器 | 稱呼 | 職責範圍 |
|---|---|---|
| Bootstrap ClassLoader | 啟動類加載器 | 加載 JDK 核心庫(rt.jar、resources.jar、charsets.jar 等) |
| Extension ClassLoader | 擴展類加載器 | 加載 JAVA_HOME/jre/lib/ext/ 目錄下所有 JAR |
| App ClassLoader | 系統類加載器 | 加載應用程式 classpath 下所有類與 JAR |
// 方式一
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urls) System.out.println(url.toExternalForm());
// 方式二
System.out.println(System.getProperty("sun.boot.class.path"));
ClassNotFoundExceptionjava.lang.String)只能由 Bootstrap 加載,防止惡意代碼替換核心 APIJVM 判定兩個類是否相同,需同時滿足:
即使字節碼完全一致,不同加載器加載也視為不同類。
public class NetworkClassLoader extends ClassLoader {
private String rootUrl;
public NetworkClassLoader(String rootUrl) { this.rootUrl = rootUrl; }
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getClassData(name); // 從網絡/文件獲取字節碼
if (classData == null) throw new ClassNotFoundException();
return defineClass(name, classData, 0, classData.length);
}
// getClassData() 實現略...
}
public class SimpleURLClassLoader extends URLClassLoader {
public static String projectClassPath = "E:/workspace/project/bin/";
public SimpleURLClassLoader() {
super(getMyURLs()); // 指定掃描路徑
}
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// 可選:打破雙親委派,實現熱插拔
// 但 java.* 開頭類仍由系統加載器處理
}
}
類必須同時滿足三條件才能被卸載:
java.lang.Class 對象無任何引用注意:GC 時機不可控,類卸載同樣不可控。
SimpleURLClassLoader loader = new SimpleURLClassLoader();
Class clazzA = loader.load("testjvm.testclassloader.A");
Object a = clazzA.newInstance();
// 清除所有引用
a = null;
clazzA = null;
loader = null;
System.gc(); // 僅建議執行 GC
System.out.println("GC over");
參考文檔:
CSDN 類加載詳解 |
OSChina 類加載實戰
