1. 程式人生 > >使用 VisualVM 進行效能分析及調優

使用 VisualVM 進行效能分析及調優

原文轉載

概述

開發大型 Java 應用程式的過程中難免遇到記憶體洩露、效能瓶頸等問題,比如檔案、網路、資料庫的連線未釋放,未優化的演算法等。隨著應用程式的持續執行,可能會造成整個系統執行效率下降,嚴重的則會造成系統崩潰。為了找出程式中隱藏的這些問題,在專案開發後期往往會使用效能分析工具來對應用程式的效能進行分析和優化。

VisualVM 是一款免費的效能分析工具。它通過 jvmstat、JMX、SA(Serviceability Agent)以及 Attach API 等多種方式從程式執行時獲得實時資料,從而進行動態的效能分析。同時,它能自動選擇更快更輕量級的技術儘量減少效能分析對應用程式造成的影響,提高效能分析的精度。

本文將對 VisualVM 的主要功能逐一介紹並探討如何利用獲得的資料進行效能分析及調優。

背景知識

  • 監視:監視是一種用來檢視應用程式執行時行為的一般方法。通常會有多個檢視(View)分別實時地顯示 CPU 使用情況、記憶體使用情況、執行緒狀態以及其他一些有用的資訊,以便使用者能很快地發現問題的關鍵所在。
  • 轉儲:效能分析工具從記憶體中獲得當前狀態資料並存儲到檔案用於靜態的效能分析。Java 程式是通過在啟動 Java 程式時新增適當的條件引數來觸發轉儲操作的。它包括以下三種:
    • 系統轉儲:JVM 生成的本地系統的轉儲,又稱作核心轉儲。一般的,系統轉儲資料量大,需要平臺相關的工具去分析,如 Windows 上的 windbg 和 Linux 上的 gdb。
    • Java 轉儲:JVM 內部生成的格式化後的資料,包括執行緒資訊,類的載入資訊以及堆的統計資料。通常也用於檢測死鎖。
    • 堆轉儲:JVM 將所有物件的堆內容儲存到檔案。
  • 快照:應用程式啟動後,效能分析工具開始收集各種執行時資料,其中一些資料直接顯示在監視檢視中,而另外大部分資料被儲存在內部,直到使用者要求獲取快照,基於這些儲存的資料的統計資訊才被顯示出來。快照包含了應用程式在一段時間內的執行資訊,通常有 CPU 快照和記憶體快照兩種型別。
    • CPU 快照:主要包含了應用程式中函式的呼叫關係及執行時間,這些資訊通常可以在 CPU 快照檢視中進行檢視。
    • 記憶體快照:主要包含了記憶體的分配和使用情況、載入的所有類、存在的物件資訊及物件間的引用關係等。這些資訊通常可以在記憶體快照檢視中進行檢視。
  • 效能分析:效能分析是通過收集程式執行時的執行資料來幫助開發人員定位程式需要被優化的部分,從而提高程式的執行速度或是記憶體使用效率,主要有以下三個方面:
    • CPU 效能分析:CPU 效能分析的主要目的是統計函式的呼叫情況及執行時間,或者更簡單的情況就是統計應用程式的 CPU 使用情況。通常有 CPU 監視和 CPU 快照兩種方式來顯示 CPU 效能分析結果。
    • 記憶體效能分析:記憶體效能分析的主要目的是通過統計記憶體使用情況檢測可能存在的記憶體洩露問題及確定優化記憶體使用的方向。通常有記憶體監視和記憶體快照兩種方式來顯示記憶體效能分析結果。
    • 執行緒效能分析:執行緒效能分析主要用於在多執行緒應用程式中確定記憶體的問題所在。一般包括執行緒的狀態變化情況,死鎖情況和某個執行緒線上程生命期內狀態的分佈情況等

VisualVM 是一個性能分析工具,自從 JDK 6 Update 7 以後已經作為 Oracle JDK 的一部分,位於 JDK 根目錄的 bin 資料夾下。VisualVM 自身要在 JDK6 以上的版本上執行,但是它能夠監控 JDK1.4 以上版本的應用程式。下面主要介紹如何安裝 VisualVM 以及各種 VisualVM 上的外掛。

VisualVM 專案的官方網站目前提供英文版本和多語言支援版本下載。多語言版本主要支援英語、日語以及中文三種語言。如果下載安裝多語言版本的 VisualVM,安裝程式會依據作業系統的當前語言環境去安裝相應 VisualVM 的語言版本。最新 VisualVM 版本主要支援的作業系統包括:Microsoft Windows (7, Vista, XP, Server)、Linux、Sun Solaris、Mac OS X、HP-UX 11i。本文以 Microsoft Windows XP 為安裝環境並支援中文。

  • 將 VisualVM 安裝程式解壓縮到本地系統。
  • 導航至 VisualVM 安裝目錄的 bin 目錄,然後啟動 jvisualvm.exe。

VisualVM 外掛中心提供很多外掛以供安裝向 VisualVM 新增功能。可以通過 VisualVM 應用程式安裝,或者從 VisualVM 外掛中心手動下載外掛,然後離線安裝。另外,使用者還可以通過下載外掛分發檔案 (.nbm 檔案 ) 安裝第三方外掛為 VisualVM 新增功能。

從 VisualVM 外掛中心安裝外掛安裝步驟 :

  • 從主選單中選擇“工具”>“外掛”。
  • 在“可用外掛”標籤中,選中該外掛的“安裝”複選框。單擊“安裝”。
  • 逐步完成外掛安裝程式。

圖 1. VisualVM 外掛管理器
圖 1. VisualVM 外掛管理器

根據 .nbm 檔案安裝第三方外掛安裝步驟 :

  • 從主選單中選擇“工具”>“外掛”。
  • 在“已下載”標籤中,點選"新增外掛"按鈕,選擇已下載的外掛分發檔案 (.nbm) 並開啟。
  • 選中開啟的外掛分發檔案,並單擊"安裝"按鈕,逐步完成外掛安裝程式。

圖 2. 通過 .nbm 檔案安裝 VisualVM 外掛
圖 2. 通過 .nbm 檔案安裝 VisualVM 外掛

功能介紹

下面我們將介紹效能分析的幾種常見方式以及如何使用 VisualVM 效能分析工具進行分析。

記憶體分析

VisualVM 通過檢測 JVM 中載入的類和物件資訊等幫助我們分析記憶體使用情況,我們可以通過 VisualVM 的監視標籤和 Profiler 標籤對應用程式進行記憶體分析。

在監視標籤內,我們可以看到實時的應用程式記憶體堆以及永久保留區域的使用情況。


圖 3. 記憶體堆使用情況
圖 3. 記憶體堆使用情況

圖 4. 永久保留區域使用情況
圖 4. 永久保留區域使用情況

此外,我們也可以通過 Applications 視窗右擊應用程式節點來啟用“在出現 OOME 時生成堆 Dump”功能,當應用程式出現 OutOfMemory 例外時,VisualVM 將自動生成一個堆轉儲。


圖 5. 開啟“在出現 OOME 時生成堆”功能
圖 5. 開啟“在出現 OOME 時生成堆”功能

在 Profiler 標籤,點選“記憶體”按鈕將啟動一個記憶體分析會話,等 VisualVM 收集和統計完相關效能資料資訊,將會顯示在效能分析結果。通過記憶體效能分析結果,我們可以檢視哪些物件佔用了較多的記憶體,存活的時間比較長等,以便做進一步的優化。

此外,我們可以通過效能分析結果下方的類名過濾器對分析結果進行過濾。


圖 6. 記憶體分析結果
圖 6. 記憶體分析結果

CPU 分析

VisualVM 能夠監控應用程式在一段時間的 CPU 的使用情況,顯示 CPU 的使用率、方法的執行效率和頻率等相關資料幫助我們發現應用程式的效能瓶頸。我們可以通過 VisualVM 的監視標籤和 Profiler 標籤對應用程式進行 CPU 效能分析。

在監視標籤內,我們可以檢視 CPU 的使用率以及垃圾回收活動對效能的影響。過高的 CPU 使用率可能是由於我們的專案中存在低效的程式碼,可以通過 Profiler 標籤的 CPU 效能分析功能進行詳細的分析。如果垃圾回收活動過於頻繁,佔用了較高的 CPU 資源,可能是由記憶體不足或者是新生代和舊生代分配不合理導致的等。


圖 7. CPU 使用情況
圖 7. CPU 使用情況

在 Profiler 標籤,點選“CPU”按鈕啟動一個 CPU 效能分析會話 ,VisualVM 會檢測應用程式所有的被呼叫的方法。當進入一個方法時,執行緒會發出一個“method entry”的事件,當退出方法時同樣會發出一個“method exit”的事件,這些事件都包含了時間戳。然後 VisualVM 會把每個被呼叫方法的總的執行時間和呼叫的次數按照執行時長展示出來。

此外,我們也可以通過效能分析結果下方的方法名過濾器對分析結果進行過濾。


圖 8. CPU 效能分析結果
圖 8. CPU 效能分析結果

執行緒分析

Java 語言能夠很好的實現多執行緒應用程式。當我們對一個多執行緒應用程式進行除錯或者開發後期做效能調優的時候,往往需要了解當前程式中所有執行緒的執行狀態,是否有死鎖、熱鎖等情況的發生,從而分析系統可能存在的問題。

在 VisualVM 的監視標籤內,我們可以檢視當前應用程式中所有活動執行緒和守護執行緒的數量等實時資訊。


圖 9. 活躍執行緒情況
圖 9. 活躍執行緒情況

VisualVM 的執行緒標籤提供了三種檢視,預設會以時間線的方式展現。另外兩種檢視分別是表檢視和詳細資訊檢視。

時間線檢視上方的工具欄提供了縮小,放大和自適應三個按鈕,以及一個下拉框,我們可以選擇將所有執行緒、活動執行緒或者完成的執行緒顯示在檢視中。


圖 10. 執行緒時間線檢視
圖 10. 執行緒時間線檢視

圖 11. 執行緒表檢視
圖 11. 執行緒表檢視

我們在詳細資訊檢視中不但可以檢視所有執行緒、活動執行緒和結束的執行緒的詳細資料,而且也可以檢視某個執行緒的詳細情況。


圖 12. 執行緒詳細檢視
圖 12. 執行緒詳細檢視

快照功能

我們可以使用 VisualVM 的快照功能生成任意個性能分析快照並儲存到本地來輔助我們進行效能分析。快照為捕獲應用程式效能分析資料提供了一個很便捷的方式因為快照一旦生成可以在任何時候離線開啟和檢視,也可以相互傳閱。

VisualVM 提供了兩種型別的快照:

  • Profiler 快照:當有一個性能分析會話(記憶體或者 CPU)正在進行時,我們可以通過效能分析結果工具欄的“快照”按鈕生成 Profiler 快照捕獲當時的效能分析資料。

圖 13. Profiler 快照
圖 13. Profiler 快照
  • 應用程式快照:我們可以右鍵點選左側 Applications 視窗中應用程式節點,選擇“應用程式快照”為生成一個應用程式快照。應用程式快照會收集某一時刻的堆轉儲,執行緒轉儲和 Profiler 快照,同時也會捕獲 JVM 的一些基本資訊。

圖 14. 應用程式快照
圖 14. 應用程式快照

轉儲功能

VisualVM 能夠對正在執行的本地應用程式生成執行緒轉儲,把活動執行緒的堆疊蹤跡打印出來,幫助我們有效瞭解執行緒執行的情況,診斷死鎖、應用程式癱瘓等問題。


圖 15. 執行緒標籤及執行緒轉儲功能
圖 15. 執行緒標籤及執行緒轉儲功能

當 VisualVM 統計完應用程式內執行緒的相關資料,會把這些資訊顯示新的執行緒轉儲標籤。


圖 16. 執行緒轉儲結果
圖 16. 執行緒轉儲結果

VisualVM 能夠生成堆轉儲,統計某一特定時刻 JVM 中的物件資訊,幫助我們分析物件的引用關係、是否有記憶體洩漏情況的發生等。


圖 17. 監視標籤及堆轉儲功能
圖 17. 監視標籤及堆轉儲功能

當 VisualVM 統計完堆內物件資料後,會把堆轉儲資訊顯示在新的堆轉儲標籤內,我們可以看到摘要、類、例項數等資訊以及通過 OQL 控制檯執行查詢語句功能。

堆轉儲的摘要包括轉儲的檔案大小、路徑等基本資訊,執行的系統環境資訊,也可以顯示所有的執行緒資訊。


圖 18. 堆轉儲的摘要檢視
圖 18. 堆轉儲的摘要檢視

從類檢視可以獲得各個類的例項數和佔用堆大小數,分析出記憶體空間的使用情況,找出記憶體的瓶頸,避免記憶體的過度使用。


圖 19. 堆轉儲的類檢視
圖 19. 堆轉儲的類檢視

通過例項數檢視可以獲得每個例項內部各成員變數的值以及該例項被引用的位置。首先需要在類檢視選擇需要檢視例項的類。


圖 20. 選擇查詢例項數的類
圖 20. 選擇查詢例項數的類

圖 21. 例項數檢視
圖 21. 例項數檢視

此外,還能對兩個堆轉儲檔案進行比較。通過比較我們能夠分析出兩個時間點哪些物件被大量建立或銷燬。


圖 22. 堆轉儲的比較
圖 22. 堆轉儲的比較

圖 23. 堆轉儲的比較結果
圖 23. 堆轉儲的比較結果

執行緒轉儲和堆轉儲均可以另存成檔案,以便進行離線分析。


圖 24. 轉儲檔案的匯出
圖 24. 轉儲檔案的匯出

總結

本文首先簡要列舉了一些效能分析相關的背景知識。然後介紹了 VisualVM 的下載和安裝。最後從記憶體效能、CPU 效能、快照功能以及轉儲功能四個方面展開,進一步說明了如何使用 VisualVM 進行效能分析。通過本文的介紹,相信讀者對效能分析會有一定的瞭解,並可以利用 VisualVM 進行效能分析。


參考資料

學習

討論

加入 developerWorks 中文社群。檢視開發人員推動的部落格、論壇、組和維基,並與其他 developerWorks 使用者交流。

轉載地址:http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

下面是使用JXM協議配置的簡單的操作步驟,詳細內容可以閱讀文章後的參考資料。
1.遠端主機

(1)修改JMX服務的配置檔案:
  在JDK的根目錄/jre/lib/management中,將jmxremote.password.template另存為jmxremote.password。
用檔案編輯軟體按編輯jmxremote.password去掉
  # monitorRole QED
  # controlRole R&D
  前面的#註釋,儲存。
  如果當前系統屬於AIX、Linux或者Solaris系統還需要更改jmxremote.access和jmxremote.password的許可權
為只讀寫,命令如下
  chmod 600 jmxremote.access jmxremote.password


(2)修改JVM的啟動配置資訊:

Windows系統
set JAVA_OPTS=-Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=<hostname>
-Dcom.sun.management.jmxremote.ssl=false

AIX、Linux或者Solaris
export JAVA_OPTS="-Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=<hostname>  
-Dcom.sun.management.jmxremote.ssl=false"

例如:
set JAVA_OPTS=-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.1.24
-Dcom.sun.management.jmxremote.ssl=false

配置的說明如下:
-Dcom.sun.management.jmxremote.port                           遠端主機埠號的
-Dcom.sun.management.jmxremote.ssl=false                   是否使用SSL連線
-Dcom.sun.management.jmxremote.authenticate=false   是否開啟遠端服務許可權
-Djava.rmi.server.hostname                                              遠端主機名,使用IP地址

(3)重啟服務。

2.本地主機配置

方法一
  進入<JDK_HOME>\bin目錄,啟動JConsole命令列工具。在JConsole的新連線中新增運程計算機資訊。
<hostname>:<port>或者service:jmx:<protocol>:<sap>
例如:192.168.1.24:1099或者service:jmx:rmi:///jndi/rmi://192.168.1.24:1099 
  <hostname> 檢測伺服器IP地址
  <port>     運程主機埠 
方法二
  JDK 1.6以上版本包含了一個簡單版本的jvisualvm.exe。在Remote上右鍵選單中選擇Add Remote host,輸入運程計算機Host name,實際上就是要檢測的遠端計算機IP地址。在配置好的遠端主機上右鍵選擇Add JMX Connection...,按照方法一中要求的格式輸入,遠端主機資訊。

visualvm的下載地址如下: