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

JVM 類別卸載與類別更新機制深度解析

     編輯:Java 相關知識

規範定義:何時會卸載類別?

JVM Spec 僅兩句話:

唯有載入該類別的 ClassLoader 實例 變為 unreachable 時,類別才可能被卸載。啟動類載入器永遠 reachable,系統類別永不卸載。

JLS 12.7 補充:類別卸載屬效能優化,語意不可依賴,對程式碼透明。API 無顯式卸載介面,故:

  1. 已載入類別被卸載機率極低、時機不確定。
  2. 特定 ClassLoader 載入的類別在執行期可視為無法更新。

Unreachable 狀態分析

Reachable = 任何活執行緒可透過引用鏈存取。Finalizer-reachable 僅透過 finalizer 可達。若 ClassLoader 實例長期被快取或廣泛引用,極難達到 unreachable。

三大實測場景

場景載入器結果說明
自訂 ClassLoaderMyURLClassLoader可卸載將載入器變數設 null + System.gc(),輸出 [Unloading class MyClass]
系統類載入器AppClassLoader不可卸載載入器實例長期被引用,GC 後類別仍在
擴充類載入器ExtClassLoader不可卸載同理,載入器實例存活

結論:僅在簡單脈絡下、自訂 ClassLoader 才可能卸載;實際應用中(特別是快取策略)幾乎不會發生。

類別更新:為何同一 ClassLoader 無法重載?

預設 loadClass 第二次直接回傳快取的 Class 實例。強制覆寫 loadClass 呼叫 defineClass 會拋 LinkageError: duplicate class definition。

可行的動態更新策略

  1. 每次建立新 ClassLoader 實例載入新版本類別。不同實例載入同名類別視為不同型別(命名空間隔離),避免 LinkageError。
  2. 用完舊 ClassLoader 明確設 null,加速其 unreachable 以利 GC 回收舊版本類別與 ClassLoader 記憶體。
  3. 接受記憶體成本:ClassLoader 實例在堆中存活較久,參考 BEA 記憶體洩漏分析。

核心原則

開發時不可假設類別會被卸載;動態更新請採「新 ClassLoader 實例隔離版本」模式,並妥善管理生命週期。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved