首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

深入 Java 類加載器:雙親委派模型與三大核心加載器全解析

     編輯:Java 相關知識

類加載器層級關係

JVM 啟動時建立三大核心類加載器,呈樹狀父子關係:

加載器類型加載範圍備註
Bootstrap ClassLoaderC++ 實現(非 Java 類)JRE/lib/rt.jar 核心類庫(java.*, javax.*)無父加載器,getClassLoader() 回傳 null
Extension ClassLoaderJava 類(ExtClassLoader)JRE/lib/ext/*.jar 擴展庫父加載器為 Bootstrap
Application ClassLoaderJava 類(AppClassLoader)用戶 classpath 指定的所有類/目錄父加載器為 Extension,預設系統加載器

驗證代碼:打印加載器鏈

public class Test1 {
    public static void main(String[] args) {
        System.out.println(Test1.class.getClassLoader().getClass().getName()); // sun.misc.Launcher$AppClassLoader
        System.out.println(System.class.getClassLoader());                      // null (Bootstrap)

        ClassLoader cl = Test1.class.getClassLoader();
        while (cl != null) {
            System.out.println(cl.getClass().getName());
            cl = cl.getParent();
        }
        System.out.println(cl); // 最後印出 null (Bootstrap)
    }
}

輸出結果:

sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null

雙親委派模型機制

雙親委派模型圖解

流程說明

  1. AppClassLoader 收到載入請求,先委派給父加載器(Extension)
  2. Extension 再委派給 Bootstrap
  3. Bootstrap 若找到類 → 直接回傳,流程結束
  4. Bootstrap 找不到 → 回傳給 Extension 嘗試載入
  5. Extension 找不到 → 回傳給 AppClassLoader 嘗試載入
  6. AppClassLoader 仍找不到 → 拋出 ClassNotFoundException

為何要雙親委派?

  • 避免重複載入:核心類(如 java.lang.String)只由 Bootstrap 載入一次,防止惡意代碼偽裝核心類
  • 隔離性:子加載器可見父加載器載入的類,父加載器不可見子加載器的類
  • 防止記憶體浪費:若無委派,多子加載器可能載入同一類產生多份位元碼

自訂類加載器應用場景

  • 熱部署/熱替換(OSGi、Tomcat 模組隔離)
  • 加密類解密載入
  • 從非標準來源載入(資料庫、網路、動態生成位元碼)

打破雙親委派的歷史案例

  • JDBC:Bootstrap 載入 DriverManager,需透過 Thread.currentThread().getContextClassLoader() 反向載入用戶實現的 Driver
  • Tomcat:各 Webapp 獨立 WebappClassLoader,優先自載,再委派父加載器(違背標準委派)
  • JDK 9+ 模組系統:引入模組層級封裝,類加載器結構更複雜
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved