iT邦幫忙

2024 iThome 鐵人賽

DAY 11
2

在我們了解完如何透過 JVM 記憶體參數 來優化 GraalVM Native Image 的效能後,雖然 Native Image 在執行效能上具有明顯優勢,但它也有一些限制。由於 Native Image 是已經編譯完成的二進位執行檔案,因此無法進行 動態分析,這意味著我們無法像在 JVM 環境中那樣,使用即時監控工具來進行即時的效能分析與診斷。

因此,針對 Native Image 的應用程式,開發者需要在開發階段事先埋設 效能記錄(Metric Log) 或使用其他效能追蹤工具來紀錄執行中的數據。舉例來說,可以利用像 Prometheus 這類的監控系統來收集應用程式的效能指標,並透過儀表板將這些數據可視化。透過這樣的設計,我們可以在生產環境中持續監控應用程式的表現,避免依賴傳統的即時監控工具。

另一方面,當應用程式運行於 JVM 模式 時,開發者仍然可以利用強大的即時監控工具,例如 VisualVM,來進行動態分析與即時效能調整。VisualVM 是一款功能完整的監控與效能分析工具,特別適合用來檢視應用程式的記憶體使用、CPU 占用和執行緒狀態等關鍵資訊。

接下來,我們將介紹如何使用 VisualVM 進行應用程式的即時監控與效能分析,幫助開發者在 JVM 環境中進一步提升應用效能。

VisualVM 簡介

VisualVM 是一款隨 Java 開發工具包(JDK)附帶的強大監控工具,提供了一個視覺化介面來監控 Java 應用程式的效能與行為。對於開發者來說,VisualVM 是診斷應用程式問題、分析記憶體使用、監控 CPU 消耗及執行階段行為分析的利器。

核心功能:

  • 記憶體與 CPU 監控:VisualVM 能即時監控堆記憶體(Heap)和非堆記憶體的使用情形,並追蹤 CPU 的使用率。這對於偵測記憶體洩漏和觀察垃圾回收運作狀況非常有幫助。
  • 執行緒分析:追蹤應用程式中的所有活動執行緒,並顯示它們的狀態,協助找出執行緒競爭(Thread Contention)或死結(Deadlock)等問題。
  • 堆記憶體傾印(Heap Dump)分析:開發者可取得 Heap Dump,並進行深入分析以找出記憶體問題,例如記憶體洩漏、大量物件配置或垃圾回收運作不佳等。
  • 效能分析(Profiling):VisualVM 的效能分析工具可以追蹤每個方法的 CPU 和記憶體使用情形,協助開發者識別程式中的效能瓶頸。
  • 整合 JMX:VisualVM 可與 Java 管理擴充(JMX)整合,提供更進階的監控與管理功能。

JMX(Java Management Extensions) 是一個 Java 平台的技術,用來監控和管理應用程式、系統和設備。它提供了一個標準化的 API 來讓開發者可以監控 Java 應用的運作狀態、執行效能調整,甚至在應用程式運行時動態修改配置。

JMX 的核心功能包括:

  1. 管理資源(MBeans):JMX 透過 MBeans(Managed Beans) 來表示應用中的資源,例如伺服器、資料庫連線池等。MBeans 提供了監控和操作應用內部狀態的方法。
  2. 監控與通知:JMX 能監控應用的各種運作指標(例如記憶體使用量、CPU 負載),並在特定事件發生時觸發通知。
  3. 遠端管理:透過 JMX,可以從遠端連線並管理 Java 應用,這對於在生產環境中監控應用狀態非常有用。

JMX 讓開發者能夠更好地了解應用程式的健康狀況,並進行有效的性能調整。

安裝

1. 下載與安裝 VisualVM

VisualVM 通常隨 Java Development Kit (JDK) 一起安裝,因此你可能已經擁有此工具。若無法找到 VisualVM 或需要最新版本,請依下列步驟進行:

  1. 前往 VisualVM 官方網站
  2. 在網站首頁點擊 Download,下載適合你作業系統的安裝檔。
  3. 完成下載後,解壓縮安裝檔並將 VisualVM 安裝到你電腦中的任意目錄。

2. 檢查 JDK 安裝

VisualVM 需要 JDK 的支持,若你的系統尚未安裝 JDK,可依下列步驟進行安裝:

  1. 前往 Oracle JDK 官方下載頁面 下載最新版本的 JDK。
  2. 根據你的作業系統(Windows、macOS 或 Linux)選擇對應的安裝檔案,並完成安裝流程。
  3. 安裝完成後,設定 環境變數,將 JAVA_HOME 指向 JDK 安裝目錄,並將 JDK 的 bin 資料夾加入 PATH 變數中。

開啟VisualVM

由於本章節僅簡要介紹VisualVM介面的一些基本功能,我們將使用最簡單的方法來讓VisualVM讀取一個簡單的運行程式,這裡可以使用前面章節提到的Hello Quarkus範例。為了節省時間,我們會直接在Windows環境下進行操作。

請直接點選bin資料夾的執行檔做開啟VisualVM的動作

https://ithelp.ithome.com.tw/upload/images/20240912/201158951m8EIgh4Ng.png

接著,你會看到如下所示的介面,以下是介面功能的簡單介紹:

應用程式面板(左側)

可看到面板列出 VisualVM 可以監控的 Java 應用程式,包括 Local本機Remote遠端 的應用程式。

  • Local(本機): 顯示目前在本機執行的 Java 應用程式。例如,可以看到:
    • VisualVM 本身的程序。
    • IntelliJ IDEA(進程 ID 8748):正在運行的 IntelliJ 開發環境。
    • Gradle Daemon(進程 ID 3772):與 Gradle 任務相關的程序。
  • Remote(遠端): 顯示已連接的遠端 Java 應用程式,允許進行遠端監控。
  • VM Coredumps: 提供本機儲存的 JVM 崩潰時生成的核心轉存檔,方便進行問題診斷。
  • JFR Snapshots: 列出使用 Java Flight Recorder 進行的應用程式快照,用於記錄應用效能問題。
  • Snapshots: 管理應用程式的記憶體和執行緒快照,以供後續分析使用。

主顯示區(右側)

  • 當在左側選取特定的應用程式後,這個區域會顯示詳細的監控數據與資訊。例如,當點擊某個進程時,會顯示其記憶體使用狀況、CPU 負載、執行緒活動等詳細資料。

工具列(上方)

  • 工具列提供常用操作,例如刷新應用程式列表、執行快照捕捉,以及啟用或停用特定監控功能。

https://ithelp.ithome.com.tw/upload/images/20240912/20115895t9ywMGfdeH.png

執行Hello Quarkus做觀測

接著開啟Intellij IDE並開啟Hello Quarkus專案

https://ithelp.ithome.com.tw/upload/images/20240912/20115895vJKcBzwX2i.png

當看到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 等)以及系統屬性配置,這些數據有助於開發者了解應用程式當前的運行環境和配置狀態。

https://ithelp.ithome.com.tw/upload/images/20240912/20115895Z2NGhkawq9.png

以下是各個分頁的功能介紹:

  • Overview(概覽):顯示應用程式的基本資訊,包括進程 ID、JVM 版本、主類別等。這是了解應用程式運行狀態的快速摘要。
  • Monitor(監控):即時監控應用程式的資源使用狀況,例如 CPU 使用率、記憶體分配和垃圾回收的頻率。
  • Threads(執行緒):顯示應用程式中所有活動執行緒的狀態,可以用來檢查執行緒數量、阻塞情況以及死結問題。
  • Sampler(取樣器):用來取樣記憶體或 CPU 使用情況,幫助分析應用的資源消耗,找出潛在的效能瓶頸。
  • Polyglot Sampler(多語言取樣器):專為支援多語言應用程式的取樣工具,可以監控如 GraalVM 等運行多種語言的環境。
  • Profiler(效能剖析器):深入剖析應用程式的方法執行時間和記憶體分配,協助辨識效能問題,提供具體的優化建議。

Monitor

Monitor(監控) 分頁的介面,顯示了應用程式的即時資源使用情況。以下是各部分訊息的解釋:

  1. CPU 使用率(CPU usage)
  • 顯示應用程式的 CPU 使用率和垃圾回收(GC)活動。從圖中可見,當前的 CPU 使用率為 0%,沒有發生任何垃圾回收行為。這個部分有助於檢查應用程式的 CPU 負載。
  1. Heap 記憶體使用情況
  • 顯示堆記憶體(Heap)的總大小和已使用的部分。從圖中可見,Heap 大小約為 150MB,已使用約 95MB,並且記憶體使用量呈現階梯式增長,這表明垃圾回收正在發生並釋放記憶體。
  • 如果要進行記憶體洩漏偵測,你可以點擊 Heap Dump 按鈕來捕捉當前的記憶體狀態,並進行分析。
  1. 已載入類別數量(Classes)
  • 顯示應用程式當前載入的類別數量,總共已載入約 10,601 個類別,且有 775 個類別已被卸載。這個區域可以幫助你檢查類別載入情況,確保沒有不必要的類別在記憶體中持續存在。(ex:程式頻繁載入類別,但類別卸載數量較少,這為記憶體洩漏的徵兆)
  1. 執行緒(Threads)
  • 顯示應用程式中的執行緒活動。當前有 25 個活躍執行緒,其中 18 個是守護執行緒(Daemon Threads)。這個部分可以用來檢查執行緒是否處於正確的狀態,並偵測是否有執行緒競爭或死結問題。
  1. Perform GC : 手動觸發垃圾回收(Garbage Collection, GC)的功能

https://ithelp.ithome.com.tw/upload/images/20240912/20115895rlIfCfodq2.png

下表為Heap Dump 的報告顯示了應用程式的記憶體狀況,包括當前堆記憶體大小、已載入類別數量、物件實例數量以及最佔用記憶體的物件類型(如 byte[]String)。透過分析這些數據,開發者可以快速找到記憶體占用最大的物件,並使用 Retained Size 功能進一步檢查是否有記憶體洩漏,進而優化應用程式的記憶體使用效率。

簡單介紹幾種常見的應用程式記憶體問題來做一個對應觀察:

  • 記憶體洩漏

    • 症狀:記憶體使用量不斷上升,即使垃圾回收後也沒有明顯下降,最終可能導致 OutOfMemoryError
    • 分析對策:使用 Heap Dump 檢查哪些物件佔用大量記憶體並且沒有被回收(使用 Retained Size 功能),找出持有這些物件的原因,檢查是否有不必要的引用。
  • 物件消耗過多記憶體

    • 症狀:特定類型的物件(如 byte[]String)佔用了大量記憶體,導致系統反應變慢。
    • 分析對策:透過 Classes by Size of Instances 找出佔用記憶體最大的物件類別,並檢查應用程式中是否有不必要的物件生成或過多的數據加載。
  • 類別載入過多

    • 症狀:類別的載入數量不斷增加,導致 Metaspace 消耗過大,甚至出現 OutOfMemoryError: Metaspace
    • 分析對策:在 Heap Dump 中檢查 Classes 區域,了解類別載入和卸載的情況,確保不會有類別洩漏或不必要的類別持續存在。

Retained Size 幫助你判斷刪除某個物件後能回收多少記憶體,對於排查記憶體洩漏和優化內存使用非常有用。

https://ithelp.ithome.com.tw/upload/images/20240912/201158956OTnnbLaCF.png

Thread

Thread 是用來捕捉應用程式中所有執行緒的當前狀態,幫助開發者分析執行緒是否有異常行為或執行緒爭用的問題。以下是這張圖中的 Thread Dump 分析介紹:

  • 圖中的每條線代表一個執行緒,並以不同顏色表示其當前的狀態:

    • 綠色(Running):執行緒正在運行。
    • 黃色(Sleeping):執行緒正在睡眠,等待被喚醒。
    • 橙色(Wait):執行緒處於等待狀態,等待某個條件滿足或等待鎖。
    • 紅色(Park/Monitor):執行緒處於阻塞狀態,通常是等待某個監視器鎖或系統資源。
  • Live Threads:表示當前應用程式中活躍的執行緒數量(25 個),其中包含 18 個守護執行緒(Daemon Threads),這些執行緒通常是後台執行的,負責系統性操作或資源管理。

  • 執行緒狀態持續時間

    • 每個執行緒旁邊的條狀圖代表該執行緒的狀態隨時間的變化,讓你可以看到每個執行緒在不同時間段內處於何種狀態。
    • 例如,某些執行緒可能長時間處於 Wait 狀態,這可能是執行緒爭用的跡象,而某些執行緒可能在 RunningSleeping 之間切換。

https://ithelp.ithome.com.tw/upload/images/20240912/20115895IOiiILsJT5.png

下圖為Thread Dump ,是 JVM 捕捉到的應用程式當前所有執行緒的狀態。具體來說,它列出了每個執行緒的名稱、優先級、執行狀態(RUNNABLE、WAITING 等)、鎖定情況及其執行堆疊。用來診斷死結、分析執行緒爭用情況,以及優化應用程式的效能。Thread Dump 以純文字格式輸出,這讓開發者可以方便地閱讀和分析。它列出了每個執行緒的狀態、執行中的方法。

以下為內容詳細解釋

  • 時間戳與 JVM 資訊
    • 時間戳:2024-09-11 23:29:44,表示這次 Thread Dump 生成的具體時間。
    • JVM 版本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 是以混合模式運行(即支援解釋與編譯模式)。
  • Threads Class SMR Info
    • _java_thread_list:這部分是 JVM 內部的技術資訊,顯示了 JVM 內部管理執行緒的資料結構。length=31 表示當前 JVM 中共有 31 個執行緒。
    • elements:列表中的每個元素都是 JVM 中執行緒的記憶體地址,通常不需要關注這部分的細節。
  • 執行緒部分
    • 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),這是一個與引用清理工作相關的鎖。

https://ithelp.ithome.com.tw/upload/images/20240912/20115895dm5y73vkPT.png

Sampler

CPU Sampler 功能用來即時監控應用程式中每個執行緒的 CPU 使用情況,並分析應用程式的性能瓶頸。下圖顯示了目前 CPU 取樣正在進行中,選擇的是 CPU Sampling 模式(也可以選擇記憶體取樣),並列出所有活躍的執行緒,如 Reference ReaperQuarkus Main Thread。每個執行緒的名稱旁邊顯示其 Total Time(總執行時間)和 Total Time (CPU)(CPU 實際使用時間),這些數據幫助開發者識別哪些執行緒佔用了最多的 CPU 資源。

從圖中可以看到,每個執行緒的總執行時間均為 4,099 毫秒,但部分執行緒的 CPU 使用時間為 0 毫秒,這表示它們可能處於等待或休眠狀態,而不是積極使用 CPU。這些數據可以幫助開發者進行性能調優,特別是在應用程式反應變慢或 CPU 負載過高的情況下,找出哪些執行緒導致了過多的資源消耗,進而進行優化。此外,若某些執行緒的總執行時間高但 CPU 使用率低,則表示它們可能處於等待狀態,這有助於檢查是否存在執行緒爭用或鎖競爭的問題。總結來說,CPU Sampler 是分析應用程式效能瓶頸的關鍵工具,幫助開發者找出最耗費資源的執行緒,進行有效的調整和優化,以提升應用程式的整體運行效率。

https://ithelp.ithome.com.tw/upload/images/20240912/201158955KFefsHCiH.png

剩餘的 Profiler 屬於較進階的使用方式,適合進行更細緻的性能調優和深度分析。例如,Profiler 不僅可以監控 CPU 和記憶體的使用情況,還能夠針對具體的 JDBC 操作鎖競爭物件分配深度 進行剖析,這對於診斷應用程式中的複雜性能瓶頸或資源爭用問題尤為有用。針對特定問題場景,你可以啟用更精細的配置選項,如跟踪對象的分配、限制分配深度或鎖的情況。總體來說,前述的基本功能已經可以解析出大部分的性能問題,而進階功能則是應對更高層次、複雜性能調整的有力工具。

如果你對 Profiler 或其他進階功能感興趣,想進一步了解具體的使用方法和設定細節,可以前往 VisualVM 的官方網站進行查詢。官網上有詳細的使用指南、教學範例和技術文檔,幫助你更深入地掌握各種功能,並有效應對不同的性能優化需求。


上一篇
Hello Quarkus GraalVM
下一篇
GraalVM快速理解-關於JVM架構實作(HotSpot)
系列文
微服務奇兵:30天Quarkus特訓營30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言