在我們了解完如何透過 JVM 記憶體參數 來優化 GraalVM Native Image 的效能後,雖然 Native Image 在執行效能上具有明顯優勢,但它也有一些限制。由於 Native Image 是已經編譯完成的二進位執行檔案,因此無法進行 動態分析,這意味著我們無法像在 JVM 環境中那樣,使用即時監控工具來進行即時的效能分析與診斷。
因此,針對 Native Image 的應用程式,開發者需要在開發階段事先埋設 效能記錄(Metric Log) 或使用其他效能追蹤工具來紀錄執行中的數據。舉例來說,可以利用像 Prometheus
這類的監控系統來收集應用程式的效能指標,並透過儀表板將這些數據可視化。透過這樣的設計,我們可以在生產環境中持續監控應用程式的表現,避免依賴傳統的即時監控工具。
另一方面,當應用程式運行於 JVM 模式 時,開發者仍然可以利用強大的即時監控工具,例如 VisualVM,來進行動態分析與即時效能調整。VisualVM 是一款功能完整的監控與效能分析工具,特別適合用來檢視應用程式的記憶體使用、CPU 占用和執行緒狀態等關鍵資訊。
接下來,我們將介紹如何使用 VisualVM 進行應用程式的即時監控與效能分析,幫助開發者在 JVM 環境中進一步提升應用效能。
VisualVM 是一款隨 Java 開發工具包(JDK)附帶的強大監控工具,提供了一個視覺化介面來監控 Java 應用程式的效能與行為。對於開發者來說,VisualVM 是診斷應用程式問題、分析記憶體使用、監控 CPU 消耗及執行階段行為分析的利器。
JMX(Java Management Extensions) 是一個 Java 平台的技術,用來監控和管理應用程式、系統和設備。它提供了一個標準化的 API 來讓開發者可以監控 Java 應用的運作狀態、執行效能調整,甚至在應用程式運行時動態修改配置。
JMX 的核心功能包括:
- 管理資源(MBeans):JMX 透過 MBeans(Managed Beans) 來表示應用中的資源,例如伺服器、資料庫連線池等。MBeans 提供了監控和操作應用內部狀態的方法。
- 監控與通知:JMX 能監控應用的各種運作指標(例如記憶體使用量、CPU 負載),並在特定事件發生時觸發通知。
- 遠端管理:透過 JMX,可以從遠端連線並管理 Java 應用,這對於在生產環境中監控應用狀態非常有用。
JMX 讓開發者能夠更好地了解應用程式的健康狀況,並進行有效的性能調整。
VisualVM 通常隨 Java Development Kit (JDK) 一起安裝,因此你可能已經擁有此工具。若無法找到 VisualVM 或需要最新版本,請依下列步驟進行:
VisualVM 需要 JDK 的支持,若你的系統尚未安裝 JDK,可依下列步驟進行安裝:
JAVA_HOME
指向 JDK 安裝目錄,並將 JDK 的 bin
資料夾加入 PATH
變數中。由於本章節僅簡要介紹VisualVM介面的一些基本功能,我們將使用最簡單的方法來讓VisualVM讀取一個簡單的運行程式,這裡可以使用前面章節提到的Hello Quarkus範例。為了節省時間,我們會直接在Windows環境下進行操作。
請直接點選bin資料夾的執行檔做開啟VisualVM的動作
接著,你會看到如下所示的介面,以下是介面功能的簡單介紹:
可看到面板列出 VisualVM 可以監控的 Java 應用程式,包括 Local本機 和 Remote遠端 的應用程式。
接著開啟Intellij IDE並開啟Hello Quarkus專案
當看到Console服務運起後,VisualVM Local就會看到對應程式項目如下,Overview 區塊顯示了 VisualVM 針對所選 Java 進程的基本資訊,包括進程 ID(PID 15508)、主機名稱(localhost)、主類別(io.quarkus.deployment.dev.DevModeMain
),以及 JVM 的詳細資料如版本(Java 17.0.1+12)和安裝路徑。還有 JVM 啟動時的參數和系統屬性設置,例如 JVM Arguments(-XX:UnlockExperimentalVMOptions
等)以及系統屬性配置,這些數據有助於開發者了解應用程式當前的運行環境和配置狀態。
以下是各個分頁的功能介紹:
Monitor(監控) 分頁的介面,顯示了應用程式的即時資源使用情況。以下是各部分訊息的解釋:
下表為Heap Dump 的報告顯示了應用程式的記憶體狀況,包括當前堆記憶體大小、已載入類別數量、物件實例數量以及最佔用記憶體的物件類型(如 byte[]
和 String
)。透過分析這些數據,開發者可以快速找到記憶體占用最大的物件,並使用 Retained Size 功能進一步檢查是否有記憶體洩漏,進而優化應用程式的記憶體使用效率。
簡單介紹幾種常見的應用程式記憶體問題來做一個對應觀察:
記憶體洩漏:
物件消耗過多記憶體:
byte[]
或 String
)佔用了大量記憶體,導致系統反應變慢。類別載入過多:
Retained Size 幫助你判斷刪除某個物件後能回收多少記憶體,對於排查記憶體洩漏和優化內存使用非常有用。
Thread 是用來捕捉應用程式中所有執行緒的當前狀態,幫助開發者分析執行緒是否有異常行為或執行緒爭用的問題。以下是這張圖中的 Thread Dump 分析介紹:
圖中的每條線代表一個執行緒,並以不同顏色表示其當前的狀態:
Live Threads:表示當前應用程式中活躍的執行緒數量(25 個),其中包含 18 個守護執行緒(Daemon Threads),這些執行緒通常是後台執行的,負責系統性操作或資源管理。
執行緒狀態持續時間
下圖為Thread Dump ,是 JVM 捕捉到的應用程式當前所有執行緒的狀態。具體來說,它列出了每個執行緒的名稱、優先級、執行狀態(RUNNABLE、WAITING 等)、鎖定情況及其執行堆疊。用來診斷死結、分析執行緒爭用情況,以及優化應用程式的效能。Thread Dump 以純文字格式輸出,這讓開發者可以方便地閱讀和分析。它列出了每個執行緒的狀態、執行中的方法。
以下為內容詳細解釋
Java HotSpot(TM) 64-Bit Server VM (17.0.12+8-LTS-jvmci-23.0-b41 mixed mode, emulated-client, sharing)
,表明使用的是 Java 17.0.12 的長期支持版,並且 JVM 是以混合模式運行(即支援解釋與編譯模式)。length=31
表示當前 JVM 中共有 31 個執行緒。Reference Handler 執行緒
"Reference Handler"
,守護執行緒(daemon thread),專門負責清理已經失效的引用物件,與 Java 的垃圾回收有關。RUNNABLE
,表示執行緒當前正在執行,並且佔用 CPU 資源。java.lang.ref.Reference.waitForReferencePendingList
本地方法(Native Method),它負責處理引用的清理工作,這是垃圾回收機制的一部分。Locked ownable synchronizers: None
,表示這個執行緒目前沒有持有任何同步鎖,沒有阻塞其他執行緒。Finalizer 執行緒
執行緒名稱:"Finalizer"
,守護執行緒,負責調用對象的 finalize()
方法,在物件即將被垃圾回收時執行清理。
執行緒狀態:WAITING (on object monitor)
,表示這個執行緒正在等待某個對象監視器鎖,通常是等待一些資源被釋放。
執行堆疊:它正處於 java.lang.Object.wait
方法中,等待在 ReferenceQueue$Lock
上的某個條件被滿足。這表示 Finalizer
正在等待其他執行緒的操作完成。
等待的對象:執行緒正在等待對象 <0x0000000703b428d8>
(即 ReferenceQueue$Lock
),這是一個與引用清理工作相關的鎖。
CPU Sampler 功能用來即時監控應用程式中每個執行緒的 CPU 使用情況,並分析應用程式的性能瓶頸。下圖顯示了目前 CPU 取樣正在進行中,選擇的是 CPU Sampling 模式(也可以選擇記憶體取樣),並列出所有活躍的執行緒,如 Reference Reaper 和 Quarkus Main Thread。每個執行緒的名稱旁邊顯示其 Total Time(總執行時間)和 Total Time (CPU)(CPU 實際使用時間),這些數據幫助開發者識別哪些執行緒佔用了最多的 CPU 資源。
從圖中可以看到,每個執行緒的總執行時間均為 4,099 毫秒,但部分執行緒的 CPU 使用時間為 0 毫秒,這表示它們可能處於等待或休眠狀態,而不是積極使用 CPU。這些數據可以幫助開發者進行性能調優,特別是在應用程式反應變慢或 CPU 負載過高的情況下,找出哪些執行緒導致了過多的資源消耗,進而進行優化。此外,若某些執行緒的總執行時間高但 CPU 使用率低,則表示它們可能處於等待狀態,這有助於檢查是否存在執行緒爭用或鎖競爭的問題。總結來說,CPU Sampler 是分析應用程式效能瓶頸的關鍵工具,幫助開發者找出最耗費資源的執行緒,進行有效的調整和優化,以提升應用程式的整體運行效率。
剩餘的 Profiler 屬於較進階的使用方式,適合進行更細緻的性能調優和深度分析。例如,Profiler 不僅可以監控 CPU 和記憶體的使用情況,還能夠針對具體的 JDBC 操作、鎖競爭 和 物件分配深度 進行剖析,這對於診斷應用程式中的複雜性能瓶頸或資源爭用問題尤為有用。針對特定問題場景,你可以啟用更精細的配置選項,如跟踪對象的分配、限制分配深度或鎖的情況。總體來說,前述的基本功能已經可以解析出大部分的性能問題,而進階功能則是應對更高層次、複雜性能調整的有力工具。
如果你對 Profiler 或其他進階功能感興趣,想進一步了解具體的使用方法和設定細節,可以前往 VisualVM 的官方網站進行查詢。官網上有詳細的使用指南、教學範例和技術文檔,幫助你更深入地掌握各種功能,並有效應對不同的性能優化需求。