# 什么是雙親委派機制
## 目錄
1. [引言](#引言)
2. [類加載器基礎](#類加載器基礎)
3. [雙親委派機制定義](#雙親委派機制定義)
4. [工作流程詳解](#工作流程詳解)
5. [實現原理分析](#實現原理分析)
6. [優勢與設計意義](#優勢與設計意義)
7. [打破雙親委派機制](#打破雙親委派機制)
8. [實際應用場景](#實際應用場景)
9. [常見問題與解決方案](#常見問題與解決方案)
10. [總結](#總結)
---
## 引言
在Java虛擬機(JVM)的類加載過程中,**雙親委派機制(Parent Delegation Model)** 是保證Java程序穩定運行的核心設計原則之一。該機制通過層次化的類加載器結構,有效解決了類重復加載、核心API被篡改等關鍵問題。本文將深入解析這一機制的實現原理、工作流程及其在Java生態中的重要意義。
---
## 類加載器基礎
### 類加載器的作用
- 將.class文件加載到JVM內存
- 轉換為方法區中的運行時數據結構
- 生成對應的`Class<?>`對象
### Java中的三類加載器
1. **Bootstrap ClassLoader**(啟動類加載器)
- 加載`JAVA_HOME/lib`下的核心類庫(如rt.jar)
- 唯一沒有父加載器的加載器
2. **Extension ClassLoader**(擴展類加載器)
- 加載`JAVA_HOME/lib/ext`目錄的擴展類
- 父加載器為Bootstrap
3. **Application ClassLoader**(應用程序類加載器)
- 加載用戶類路徑(ClassPath)上的類
- 父加載器為Extension
```java
// 查看類加載器示例
public class ClassLoaderDemo {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader()); // null (Bootstrap)
System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader()); // ExtClassLoader
System.out.println(ClassLoaderDemo.class.getClassLoader()); // AppClassLoader
}
}
“A class loader delegates the search for classes and resources to its parent class loader before attempting to find the class or resource itself.” —— Java官方文檔
AppClassLoader收到請求ExtClassLoaderExtClassLoader繼續委派給BootstrapClassLoaderBootstrap嘗試加載:
ExtClassLoader嘗試加載:
AppClassLoader在classpath中查找并加載graph TD
A[AppClassLoader] --> B[ExtClassLoader]
B --> C[BootstrapClassLoader]
C -->|加載失敗| B
B -->|加載失敗| A
ClassLoader.loadClass()的典型實現:
protected Class<?> loadClass(String name, boolean resolve) {
synchronized (getClassLoadingLock(name)) {
// 1. 檢查是否已加載
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// 2. 父加載器不為空則委派
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 3. 父加載器為空則嘗試Bootstrap加載
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
if (c == null) {
// 4. 自行查找類
c = findClass(name);
}
}
return c;
}
}
安全性保障
避免重復加載
職責分離
當用戶自定義java.lang.Object類時:
1. 加載請求最終委派到BootstrapClassLoader
2. Bootstrap已加載過JRE中的Object類
3. 直接返回已加載的Class對象
4. 自定義類永遠不會被加載
SPI服務發現(如JDBC驅動加載)
熱部署需求
// 通過重寫loadClass方法打破委派
public class CustomClassLoader extends ClassLoader {
@Override
protected Class<?> loadClass(String name, boolean resolve) {
// 1. 自定義邏輯優先處理
if (name.startsWith("com.special.")) {
return findClass(name);
}
// 2. 其他類仍走雙親委派
return super.loadClass(name, resolve);
}
}
graph BT
WebApp1[WebAppClassLoader] --> Common[CommonClassLoader]
WebApp2[WebAppClassLoader] --> Common
Common --> Shared[SharedClassLoader]
Shared --> Server[ServerClassLoader]
Server --> Bootstrap
@EnableAspectJAutoProxy(proxyTargetClass=true)控制| 異常類型 | 觸發階段 | 常見原因 |
|---|---|---|
| ClassNotFoundException | 加載階段 | 類文件不存在 |
| NoClassDefFoundError | 鏈接階段 | 類已加載但依賴缺失 |
// 熱加載示例
public class HotSwap {
public static void main(String[] args) throws Exception {
while (true) {
CustomClassLoader loader = new CustomClassLoader();
Class<?> clazz = loader.loadClass("com.example.DynamicClass");
Object instance = clazz.newInstance();
clazz.getMethod("execute").invoke(instance);
Thread.sleep(5000);
}
}
}
雙親委派機制作為Java類加載體系的核心設計: - 通過層次化委派保證類加載的有序性 - 是Java安全模型的基石之一 - 在保持穩定性的同時允許通過特定方式擴展
隨著模塊化系統(JPMS)的引入,Java 9+對類加載機制進行了進一步優化,但雙親委派的基本思想仍是理解JVM類加載過程的關鍵所在。
最佳實踐建議:在自定義類加載器時,除非有明確需求,否則應保持雙親委派機制的完整性。 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。