ClassLoader 是 Java 動態載入類的核心機制,支援熱部署、插件化、代碼熱替換等進階場景。本文系統闡述三大系統類加載器、雙親委派模型、自定義加載器實作與經典應用架構。
| 加載器 | 實現語言 | 加載範圍 | 獲取方式 |
|---|---|---|---|
| Bootstrap ClassLoader (啟動類加載器) | C++ (VM 內建) | JAVA_HOME/lib 下可識別類庫 (rt.jar 等) | Java 程式無法直接引用 |
| Extension ClassLoader (擴展類加載器) | Java | JAVA_HOME/lib/ext 目錄所有類庫 | 開發者可直接使用 |
| Application ClassLoader (應用/系統類加載器) | Java | 用戶類路徑 (Classpath) 指定類庫 | ClassLoader.getSystemClassLoader() |
Application ClassLoader 由 sun.misc.Launcher$AppClassLoader 實現,getSystemClassLoader() 內部透過 Launcher.getLauncher().getClassLoader() 取得並經 AccessController.doPrivileged 特權初始化。

核心原則:類加載請求先委派父加載器,父無法處理時子才嘗試。查找順序:Bootstrap → Extension → Application。優勢:
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class c = findLoadedClass(name); // 1. 檢查已載入
if (c == null) {
try {
if (parent != null) // 2. 委派父加載器
c = parent.loadClass(name, false);
else
c = findBootstrapClassOrNull(name); // 頂層委派 Bootstrap
} catch (ClassNotFoundException e) { /* 父找不到 */ }
if (c == null) // 3. 父失敗,自行 findClass
c = findClass(name);
}
if (resolve) resolveClass(c); // 4. 連接階段
return c;
}
}
開發者可覆寫 loadClass() 或 findClass() 實現自定義邏輯。
public class ClassLoadDemo {
public static void main(String[] args) throws Exception {
ClassLoader customLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String classFile = name.substring(name.lastIndexOf('.')+1) + ".class";
InputStream is = getClass().getResourceAsStream(classFile);
if (is == null) return super.loadClass(name);
byte[] bytes = new byte[is.available()];
is.read(bytes);
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException(name);
}
}
};
String className = "com.yuanhh.classloader.ClassLoadDemo";
Class<?> clazz = customLoader.loadClass(className);
Object obj = clazz.newInstance();
System.out.println(obj.getClass()); // class com.yuanhh.classloader.ClassLoadDemo
System.out.println(obj instanceof com.yuanhh.classloader.ClassLoadDemo); // false!
}
}
輸出 false 證明:同一 Class 文件經不同加載器載入,屬於不同類型。obj 由自定義加載器載入 (ClassLoadDemo$1),而直接引用的 ClassLoadDemo.class 由系統加載器載入 (AppClassLoader),instanceof、equals() 等判斷均基於加載器身份。