1. JMX (Java Management Extensions): JVM 監控的核心
監控就像為你的應用程式做定期健檢。若把日誌記錄比作「已經發生的事情」的日記,監控則是一組儀表,會即時顯示系統此刻的狀態:溫度、脈搏、血壓、血糖以及其他對 JVM 至關重要的指標。
它有助於了解實際使用了多少記憶體、有沒有洩漏、目前有多少執行緒以及它們的狀態——在等待、執行還是被鎖住。你可以看到垃圾回收器的觸發頻率、CPU 的負載,並及時察覺像是記憶體或執行緒數量突然上升之類的警訊。
簡而言之,記錄告訴你已經發生了什麼,而監控則顯示此刻正在發生什麼。
JMX 基礎:是什麼,為什麼需要
JMX 是 Java 中的一項技術,能讓你從內部觀察應用程式的運作,甚至進行少量控制。它透過特殊物件——MBean(Management Bean)——工作。可以把它看作 JVM 內部的「感測器」與「開關」:有些用來顯示系統狀態,有些則能稍作調整。
透過 JMX,你可以得知當前 JVM 分配了多少記憶體、多少執行緒處於活躍狀態、垃圾回收花了多少時間等等——無需修改程式碼或重啟應用程式。
它如何運作
在 JVM 中「開箱即用」就有許多 MBean,可提供下列資訊:
- 記憶體(heap、non-heap);
- 垃圾回收器(GC);
- 執行緒;
- 類別(載入/卸載數量);
- 甚至是 JVM 本身(版本、啟動參數)。
JMX 就像車上的儀表板。 你能看到速度、轉速、引擎溫度——而這些都可透過標準感測器(MBean)取得。
如何存取 JMX
最簡單的方式是使用隨 JDK 提供的標準工具 JConsole。
啟動 JConsole
- 打開終端機/命令列。
- 執行指令:
jconsole - 選擇你想監控的 Java 行程(例如你的應用程式)。
JConsole 會透過 JMX 連線到 JVM,並顯示圖表與表格:記憶體使用量、執行緒數量、垃圾回收器活動等。
範例:查看記憶體與執行緒
在 JConsole 中打開 "Memory" 與 "Threads" 分頁。你會看到已用記憶體的變化、目前有多少執行緒存活、哪些活躍、哪些在等待。
自訂 MBean
你可以建立自己的 MBean 來監控自家指標(例如已處理訂單數)。不過這屬於進階主題:標準的 MBean 已經提供了非常多資訊。
2. VisualVM — 視覺化監控與剖析
如果 JConsole 是「儀表板」,那 VisualVM 就是一整套包含 X 光、MRI 與血液分析的診斷中心。它不只用於監控,還能剖析應用程式、擷取 heap dump、分析洩漏,並查看哪些方法最耗時。
安裝與啟動 VisualVM
- VisualVM 通常隨 JDK 提供(一般為 jvisualvm),但也可於 visualvm.github.io 下載最新版本。
- 以以下指令啟動:
jvisualvm - 啟動後,你會看到本機上所有已啟動的 Java 行程清單。
連線到行程
- 在清單中找到你的行程(例如 Main 或 MyApp)。
- 雙擊它——會開啟該行程的資訊分頁。
- 完成!現在你可以看到:
- 即時的 CPU 與記憶體使用狀況。
- 執行緒數量與其狀態。
- 已載入的類別清單。
- 能夠擷取 heap dump 與 thread dump。
VisualVM 的主要功能
使用 VisualVM 可以觀察記憶體的使用情況——包含 heap 與 non-heap。圖表可顯示消耗是在成長還是趨於穩定。若想檢查垃圾回收,按下 "Perform GC" 按鈕——JVM 會立即嘗試清理記憶體。你也可以建立 heap dump(記憶體快照)並加以分析以找出洩漏。
它也會顯示執行緒狀態:目前啟動了多少、哪些在運作、哪些在等待或被鎖住。若發生 deadlock,VisualVM 能協助偵測並顯示互鎖。
要做深入分析可以使用剖析器:你會看到「熱點」方法,也就是最耗費 CPU 時間或記憶體的方法。這在診斷性能突然下降時特別有用。
範例:監控一個迷你應用
public class MemoryLeakDemo {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memoryConsumers = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
memoryConsumers.add(new byte[1024 * 1024]); // 1 MB
Thread.sleep(100); // 稍微等待,讓圖表更平滑
}
System.out.println("完成!別忘了到 VisualVM 看看 :)");
Thread.sleep(60000); // 保持應用程式開著以便分析
}
}
現在:
- 啟動程式。
- 打開 VisualVM,連線到該行程。
- 觀察記憶體使用量如何成長。
- 擷取 heap dump,找出佔用記憶體的陣列。
3. Java Flight Recorder (JFR):JVM 的黑盒
什麼是 JFR
Java Flight Recorder 是內建於 JVM 中,用於收集應用程式運作事件的工具。它就像「黑盒」:JFR 會記錄在 JVM 中發生的事情,之後可用來找出瓶頸或事故原因。
JFR 會收集:
- GC 事件;
- 執行緒資訊;
- 方法呼叫頻率與時間剖析;
- 停頓與延遲;
- 例外與錯誤。
如何啟用 JFR
自 Java 11 起,OpenJDK 已內建 JFR。
搭配 JFR 啟動
java -XX:StartFlightRecording=filename=recording.jfr,duration=60s,settings=profile -jar MyApp.jar
- filename=recording.jfr — 存放錄製檔的位置。
- duration=60s — 錄製時長。
- settings=profile — 詳細程度(default、profile、continuous)。
查看結果
要分析 .jfr 檔,可使用 JDK Mission Control(JMC):
- 下載 JMC:jdk.java.net/jmc
- 打開檔案 recording.jfr。
- 檢視圖表、「熱點」方法、GC 停頓與執行緒活動。
範例:擷取「黑盒」
- 使用 JFR 啟動應用程式(見上方指令)。
- 打開 JDK Mission Control,載入錄製檔。
- 評估 CPU/記憶體的「熱點」、垃圾回收頻率以及活躍執行緒數量。
4. 實作:監控一個應用
import java.util.ArrayList;
import java.util.List;
public class MonitoringExample {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memory = new ArrayList<>();
for (int i = 0; i < 50; i++) {
memory.add(new byte[2 * 1024 * 1024]); // 2 MB
Thread.sleep(500);
}
// 啟動一個執行緒
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
System.out.println("背景執行緒在運作...");
} catch (InterruptedException e) {
break;
}
}
}).start();
Thread.sleep(20000); // 保持應用程式開著以便監控
}
}
操作步驟:
- 啟動程式。
- 打開 VisualVM,找到行程,查看記憶體圖與執行緒。
- 嘗試擷取 heap dump 與 thread dump。
- 進階:搭配 JFR 啟動並在 JMC 中查看結果。
5. 實用細節
監控工具比較表
| 工具 | 適用於 | 如何啟動 | 特色 |
|---|---|---|---|
| JConsole (JMX) | JVM 基本指標、執行緒、GC | |
簡單、隨 JDK 提供 |
| VisualVM | 監控、剖析、heap dump | |
圖表、記憶體/CPU 分析 |
| Java Flight Recorder | JVM 事件的深入分析 | |
在 JMC 中分析,「黑盒」 |
| JDK Mission Control | 查看 JFR 檔案 | 獨立程式 | 詳細分析與報告 |
建議
- 不只在正式環境,在測試階段也要監控。 這樣能更早抓到記憶體洩漏與「卡住」的執行緒。
- Heap dump 一點也不可怕! 懷疑洩漏時就擷取記憶體傾印,並在 VisualVM 中分析。
- 別害怕嘗試使用 JFR。 即使一開始看不懂,事件與圖表也能幫你找出瓶頸。
- JMX 可以程式化使用。 例如把指標傳送到 Prometheus/Grafana。
- 剖析器不適合長期常駐。 請在需要時才啟用,否則應用程式可能變慢。
6. 監控 JVM 的常見錯誤
錯誤 1:完全不監控。 許多新手認為只要應用程式「能跑」,一切就沒問題。其實記憶體與執行緒問題常在高負載或一段時間後才顯現。別偷懶,至少偶爾打開 VisualVM/JConsole 看一下。
錯誤 2:在大型應用上毫無準備就擷取 heap dump。 大型應用的 heap dump 可能以 GB 計,還可能讓行程「凍住」數秒。請在測試環境進行,或若是正式環境,選擇離峰時段。
錯誤 3:忽視 GC 與執行緒指標。 長時間高比例的 GC 開銷是警訊!若執行緒數量穩定成長——請找出執行緒洩漏。
錯誤 4:不分析監控結果。 只打開 VisualVM 還不夠。檢視哪些物件佔用記憶體、哪些方法「吃」了 CPU、為什麼出現 deadlock。請剖析堆疊追蹤與根因。
錯誤 5:在正式環境不加思索地使用剖析器。 剖析可能顯著拖慢應用程式。只在診斷時啟用,而非長期常駐。
GO TO FULL VERSION