JVM 是開發者視為理所當然的「黑盒」,很少有人深入理解其任務分派、垃圾回收、線程遷移、JIT 編譯等內部運作。不熟悉 JVM 不僅影響應用效能,更會在故障發生時讓排查陷入困境。本文精選 5 個高價值命令行標記,助你診斷與調優 JVM。
代碼中濫用 System.gc() 是典型反模式:
// 釋放了一堆對象,告訴「愚蠢」的 GC 快回收!
System.gc();
若 JVM 運行分代收集器(大多數情況),System.gc() 會強制觸發全堆掃描(Full GC),成本是常規 GC 的數個數量級。
啟動參數加入:
-XX:+DisableExplicitGC
此標記將 System.gc() 轉為無操作。可對比啟用/禁用前後的 GC 日誌與應用吞吐量,評估顯式 GC 的真實影響。
JVM 拋出 OutOfMemoryError 時往往無法附加調試器,偶發性問題極難復現。
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dumps/heap.hprof # 可選,指定輸出路徑
JVM 會在崩潰前生成 .hprof 快照,事後用 jhat、MAT (Memory Analyzer Tool)、JVisualVM 分析對象佔用、洩漏鏈路。確保進程對目錄有寫權限。
需覆蓋 JRE 核心類(如修補 java.lang.Integer、接入新加密提供商),但直接修改 rt.jar 違反許可協議且極其危險。
-Xbootclasspath:/new/path:rt.jar:... 完全替換引導類路徑(高風險)。-Xbootclasspath/p:/patched/classes 前置 路徑(優先加載補丁類)。-Xbootclasspath/a:/extra/jars 追加 路徑(補充擴展類)。例:將修正後的 Integer 放入 mods/,啟動加 -Xbootclasspath/p:mods 即可優先加載。
| 子標記 | 用途 | 典型輸出信息 |
|---|---|---|
-verbose:gc | GC 診斷 | 每次 GC 耗時、堆變化、[Full GC] 標記 |
-verbose:class | 類加載診斷 | 類加載時機、來源(JAR 路徑)、解決 ClassLoader 衝突 |
-verbose:jni | JNI 診斷 | 本地庫加載、Native 方法調用 |
生產建議:用 -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags (JDK 9+) 替代 -verbose:gc,結構化日誌便於分析工具解析。
執行 java -X 可查看當前 JVM 支持的所有 -X 參數,例如:
-Xint:純解釋模式運行(驗證 JIT 編譯器效果/BUG)。-Xloggc:/path/gc.log:GC 日誌寫文件而非標準輸出。非標準參數(
-XX/-X)不承諾跨版本穩定,生產環境僅保留經充分驗證的 GC 調優參數。其餘僅作診斷階段臨時使用,問題解決後應移除。
| 參數 | 核心作用 | 適用階段 | 風險等級 |
|---|---|---|---|
-XX:+DisableExplicitGC | 禁用 System.gc() | 全生命周期 | 低 |
-XX:+HeapDumpOnOutOfMemoryError | OOM 自動堆轉儲 | 全生命周期 | 低(佔磁盤) |
-Xbootclasspath/p | 前置引導類路徑 | 核心類修補/測試 | 高 |
-verbose:class | 類加載追蹤 | 啟動/類衝突排查 | 低(日誌量大) |
| 查看所有非標準參數 | 學習/探索 | 無 |