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

JVM TI 實戰(二):動態熱替換運行時 Class 文件

     編輯:Java 相關知識

生產環境應用伺服器(如 WebLogic 生產模式)不支援熱部署,業務邏輯變更往往需重啟。利用 JVMTI(透過 JDI 高層 API)可實現無重啟動態替換已載入類。

核心流程

  1. Attach 目標 JVM:啟動參數加入 -Xdebug -Xrunjdwp:transport=dt_socket,address=9191,server=y,suspend=n,使用 VirtualMachine.attach() 連接。
  2. 準備新類字節碼:從當前 ClassPath 讀取目標 .class 文件轉為 byte[]。
  3. 查找目標 JVM 中對應 ReferenceType:vm.classesByName(className)。
  4. 調用 vm.redefineClasses(Map<ReferenceType, byte[]>) 完成熱替換。

關鍵代碼片段

public void reloadClasses(List<String> toReloads) {
  Map<ReferenceType, byte[]> toReloadMap = new HashMap<>();
  for (String className : toReloads) {
    InputStream is = getClass().getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");
    if (is == null) throw new RuntimeException("Class not found in classpath: " + className);
    List<ReferenceType> refs = vm.classesByName(className);
    if (refs.isEmpty()) throw new RuntimeException("Class not loaded in target JVM: " + className);
    toReloadMap.put(refs.get(0), toByteArray(is));
  }
  if (!vm.canRedefineClasses()) throw new RuntimeException("Target VM does not support RedefineClasses");
  vm.redefineClasses(toReloadMap);
}

三大前置條件(缺一不可)

  • ✅ 新類文件存在於 調試端 ClassPath 中。
  • ✅ 目標類已在 目標 JVM 載入(未載入無法 redefine)。
  • ✅ 目標 JVM 支援 canRedefineClasses() == true(部分 VM 實現受限)。

限制與風險

  • Schema 不可變:僅允許修改方法體、常數池,不能增減欄位、方法、改變繼承關係。
  • 線程安全:替換瞬間正在執行舊代碼的線程可能拋出 VerifyError 或行為異常,建議低峰期操作。
  • 非持久化:JVM 重啟後失效,需配合部署流程落盤。

適用場景

緊急修復線上 Bug(如邏輯判斷錯誤、參數校驗遺漏)、動態調整業務規則參數、AOP 切面注入臨時診斷代碼。非替代標準發布流程。

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