| 機制 | 含義 | 作用 |
|---|---|---|
| 雙親委派 | 加載請求先委派給父加載器,父無法加載時子才嘗試 | 保證核心類庫統一、防止惡意覆蓋、避免重複加載 |
| 可見性 | 父加載器加載的類對子可見,子加載的類父不可見 | 實現命名空間隔離,基礎類庫共享 |
| 單一性 | 同一類加載器實例下,同一全限定名類只加載一次 | 保證運行時類唯一性 |
Bootstrap ClassLoader (啟動類加載器)
↑ C++ 實現,非 Java 類,加載 /jre/lib/rt.jar 等核心庫
Extension ClassLoader (擴展類加載器)
↑ Java 實現,加載 /jre/lib/ext/*.jar
Application ClassLoader (應用/系統類加載器)
↑ Java 實現,加載 classpath (-cp) 指定路徑,getClassLoader() 返回此對象
String.class.getClassLoader() == null 證明核心類由 Bootstrap 加載。
protected Class<?> loadClass(String name, boolean resolve) {
synchronized (getClassLoadingLock(name)) {
Class<?> c = findLoadedClass(name); // 1. 緩存檢查
if (c == null) {
try {
if (parent != null) c = parent.loadClass(name, false); // 2. 委派父加載
else c = findBootstrapClassOrNull(name); // 3. 委派 Bootstrap
} catch (ClassNotFoundException ignored) {}
if (c == null) c = findClass(name); // 4. 自己查找 (子類實現)
}
if (resolve) resolveClass(c); // 5. 連接 (可選)
return c;
}
}
class NetworkClassLoader extends ClassLoader {
private String host; private int port;
@Override protected Class<?> findClass(String name) {
byte[] data = loadClassData(name); // 從網絡讀取 .class 字節碼
return defineClass(name, data, 0, data.length); // 定義為 Class 對象
}
private byte[] loadClassData(String name) { /* HTTP 下載邏輯 */ }
}
關鍵點:只需覆寫 findClass(),**不要覆寫 loadClass()** 除非打破雙親委派(如熱部署、模塊化框架)。
Thread.currentThread().getContextClassLoader()) 反向加載服務實現instanceof、強轉、靜態字段均不共享<clinit>)類加載器是 Java 動態性的基石。**雙親委派保安全,可見性做隔離,單一性保唯一**。理解源碼 loadClass 模板方法,掌握 findClass 覆寫點,才能驾驭熱部署、模塊化、多版本共存等高級場景。**除非框架開發,業務代碼極少自定義類加載器。**