生產環境 JVM 突發 OOM 或 GC 停頓,往往因啟動腳本缺少 -XX:+PrintGCDetails 等診斷參數。傳統做法是停機、改腳本、重啟、祈禱問題復現——這不僅造成服務中斷,問題還可能因環境變化而無法復現。
幸運的是,JDK 自帶的 jinfo 工具支援運行時動態修改可管理旗標,讓我們在不重啟的情況下即時開啟 GC 日誌,快速定位問題。
jinfo 是 JDK 隨附的命令列診斷工具,可查看並修改執行中 Java 進程的 JVM 旗標。關鍵在於:只有標註為 manageable 的旗標才能動態調整。
java -XX:+PrintFlagsFinal -version | grep manageable
輸出範例(節錄):
bool HeapDumpOnOutOfMemoryError = false {manageable}
bool PrintGC = false {manageable}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCTimeStamps = false {manageable}
標註 {manageable} 的即為可透過 jinfo -flag 動態切換的選項。
jps
# 輸出範例:
# 12278 HighAllocationRate
# 12279 Jps
# 12269 JConsole
假設目標應用 PID 為 12278。
jinfo -flag +PrintGCDetails 12278
jinfo -flag +PrintGC 12278
注意:與啟動參數不同,運行時必須同時開啟 PrintGC 與 PrintGCDetails;啟動時僅需 PrintGCDetails 會自動隱含開啟 PrintGC。
控制台將即時滾動輸出類似下列 GC 日誌:
[GC (Allocation Failure) [PSYoungGen: 876416K->102624K(909312K)] 1094420K->320820K(1161216K), 0.2173131 secs]
[Times: user=0.74 sys=0.00, real=0.22 secs]
[GC (Allocation Failure) [PSYoungGen: 890304K->102240K(917504K)] 1108924K->320956K(1169408K), 0.2446639 secs]
[Times: user=0.82 sys=0.01, real=0.25 secs]
jinfo -flag -PrintGCDetails 12278
jinfo -flag -PrintGC 12278
| 旗標 | 用途 |
|---|---|
HeapDumpOnOutOfMemoryError | OOM 時自動產生 Heap Dump |
PrintGCDateStamps | GC 日誌加入日期時間戳 |
PrintGCTimeStamps | GC 日誌加入相對時間戳 |
CMSAbortablePrecleanWaitMillis | CMS 預清理等待閾值調優 |
-Xmx、-Xms、-XX:NewRatio 等非 manageable 旗標無法運行時調整,仍需重啟。-Xloggc:/path/gc.log 以持久化。掌握 jinfo 動態調整 manageable 旗標的技巧,能讓你在故障現場「不停機、不重啟、即時可見」地獲取關鍵診斷數據,大幅縮短 MTTR(平均修復時間)。配合 jstack、jmap、jstat 等工具,構建完整的 JVM 故障診斷工具箱。
專家建議:若系統長期面臨效能調優壓力,引入 APM(如 Pinpoint、SkyWalking)或持續分析工具(如 Plumbr、Java Flight Recorder)可實現更主動、全維度的監控,減少臨時排查成本。