有了這款可視化工具,Java 應用性能調優 so easy。。。

  • JVisualVM 簡介
  • 案例分析
  • 準備模擬內存洩漏樣例
  • 使用JVisualVM分析內存洩漏
  • JVisualVM 遠程監控 Tomcat

JVisualVM 簡介

VisualVM 是Netbeans的profile子項目,已在JDK6.0 update 7 中自帶,能夠監控線程,內存情況,查看方法的CPU時間和內存中的對 象,已被GC的對象,反向查看分配的堆棧(如100個String對象分別由哪幾個對象分配出來的)。在JDK_HOME/bin(默認是C:\Program Files\Java\jdk1.6.0_13\bin)目錄下面,有一個jvisualvm.exe文件,雙擊打開,從UI上來看,這個軟件是基於NetBeans開發的了。

VisualVM 提供了一個可視界面,用於查看 Java 虛擬機 (Java Virtual Machine, JVM) 上運行的基於 Java 技術的應用程序的詳細信息。VisualVM 對 Java Development Kit (JDK) 工具所檢索的 JVM 軟件相關數據進行組織,並通過一種使您可以快速查看有關多個 Java 應用程序的數據的方式提供該信息。您可以查看本地應用程序或遠程主機上運行的應用程序的相關數據。此外,還可以捕獲有關 JVM 軟件實例的數據,並將該數據保存到本地系統,以供後期查看或與其他用戶共享。

雙擊啟動 jvisualvm.exe,啟動起來後和jconsole 一樣同樣可以選擇本地和遠程,如果需要監控遠程同樣需要配置相關參數。

主界面如下;

有了這款可視化工具,Java 應用性能調優 so easy。。。

VisualVM可以根據需要安裝不同的插件,每個插件的關注點都不同,有的主要監控GC,有的主要監控內存,有的監控線程等。

有了這款可視化工具,Java 應用性能調優 so easy。。。

如何安裝:

1、從主菜單中選擇“工具”>“插件”。2、在“可用插件”標籤中,選中該插件的“安裝”複選框。單擊“安裝”。3、逐步完成插件安裝程序。

我這裡以 Eclipse(pid 22296)為例,雙擊後直接展開,主界面展示了系統和jvm兩大塊內容,點擊右下方jvm參數和系統屬性可以參考詳細的參數信息.

有了這款可視化工具,Java 應用性能調優 so easy。。。

因為VisualVM的插件太多,我這裡主要介紹三個我主要使用幾個:監控、線程、Visual GC

監控的主頁其實也就是,cpu、內存、類、線程的圖表

有了這款可視化工具,Java 應用性能調優 so easy。。。

線程和jconsole功能沒有太大的區別

有了這款可視化工具,Java 應用性能調優 so easy。。。

Visual GC 是常常使用的一個功能,可以明顯的看到年輕代、老年代的內存變化,以及gc頻率、gc的時間等。

有了這款可視化工具,Java 應用性能調優 so easy。。。

以上的功能其實jconsole幾乎也有,VisualVM更全面更直觀一些,另外VisualVM非常多的其它功能,可以分析dump的內存快照,

dump出來的線程快照並且進行分析等,還有其它很多的插件大家可以去探索

有了這款可視化工具,Java 應用性能調優 so easy。。。

案例分析

準備模擬內存洩漏樣例

1、定義靜態變量HashMap

2、分段循環創建對象,並加入HashMap

代碼如下:

<code>

import

 java.util.HashMap;

import

 java.util.Map;

public

 

class

 

CyclicDependencies

 {

         

private

 

static

 

final

 Map 

map

 = 

new

 HashMap();     

public

 

static

 

void

 

main

(String args[])

{         

try

 {             Thread.sleep(

10000

);         } 

catch

 (InterruptedException e) {             e.printStackTrace();         }                  

for

(

int

 i=

0

; i<

1000000

;i++){             TestMemory t = 

new

 TestMemory();             

map

.put(

"key"

+i,t);         }         System.out.println(

"first"

);                  

try

 {             Thread.sleep(

10000

);         } 

catch

 (InterruptedException e) {             e.printStackTrace();         }         

for

(

int

 i=

0

; i<

1000000

;i++){             TestMemory t = 

new

 TestMemory();             

map

.put(

"key"

+i,t);         }         System.out.println(

"second"

);         

try

 {             Thread.sleep(

10000

);         } 

catch

 (InterruptedException e) {             e.printStackTrace();         }         

for

(

int

 i=

0

; i<

3000000

;i++){             TestMemory t = 

new

 TestMemory();             

map

.put(

"key"

+i,t);         }         System.out.println(

"third"

);         

try

 {             Thread.sleep(

10000

);         } 

catch

 (InterruptedException e) {             e.printStackTrace();         }         

for

(

int

 i=

0

; i<

4000000

;i++){             TestMemory t = 

new

 TestMemory();             

map

.put(

"key"

+i,t);         }         System.out.println(

"forth"

);         

try

 {             Thread.sleep(Integer.MAX_VALUE);         } 

catch

 (InterruptedException e) {             e.printStackTrace();         }         System.out.println(

"qqqq"

);     } }/<code>

3、配置jvm參數如下:

<code>         -Xms512m
         -Xmx512m
         -XX:-UseGCOverheadLimit
         -XX:MaxPermSize=50m/<code>

4、運行程序並打卡visualvm監控

使用JVisualVM分析內存洩漏

1、查看Visual GC標籤,內容如下,這是輸出first的截圖

有了這款可視化工具,Java 應用性能調優 so easy。。。

這是輸出forth的截圖:

有了這款可視化工具,Java 應用性能調優 so easy。。。

通過2張圖對比發現:

有了這款可視化工具,Java 應用性能調優 so easy。。。

有了這款可視化工具,Java 應用性能調優 so easy。。。

老生代一直在gc,當程序繼續運行可以發現老生代gc還在繼續:

有了這款可視化工具,Java 應用性能調優 so easy。。。

增加到了7次,但是老生代的內存並沒有減少。說明存在無法被回收的對象,可能是內存洩漏了。

如何分析是那個對象洩漏了呢?打開抽樣器標籤:點擊後如下圖:

有了這款可視化工具,Java 應用性能調優 so easy。。。

按照程序輸出進行堆dump,當輸出second時,dump一次,當輸出forth時dump一次。

進入最後dump出來的堆標籤,點擊類:

有了這款可視化工具,Java 應用性能調優 so easy。。。

點擊右上角:“與另一個堆存儲對比”。如圖選擇第一次導出的dump內容比較:

有了這款可視化工具,Java 應用性能調優 so easy。。。

比較結果如下:

有了這款可視化工具,Java 應用性能調優 so easy。。。

可以看出在兩次間隔時間內TestMemory對象實例一直在增加並且多了,說明該對象引用的方法可能存在內存洩漏。

如何查看對象引用關係呢?

右鍵選擇類TestMemory,選擇“在實例視圖中顯示”,如下所示:

有了這款可視化工具,Java 應用性能調優 so easy。。。

左側是創建的實例總數,右側上部為該實例的結構,下面為引用說明,從圖中可以看出在類CyclicDependencies裡面被引用了,並且被HashMap引用。

如此可以確定洩漏的位置,進而根據實際情況進行分析解決。

JVisualVM 遠程監控 Tomcat

1、修改遠程tomcat的catalina.sh配置文件,在其中增加:

  1. JAVA_OPTS="$JAVA_OPTS
  2. -Djava.rmi.server.hostname=192.168.122.128
  3. -Dcom.sun.management.jmxremote.port=18999
  4. -Dcom.sun.management.jmxremote.ssl=false
  5. -Dcom.sun.management.jmxremote.authenticate=false"這次配置先不走權限校驗。只是打開jmx端口。2、打開jvisualvm,右鍵遠程,選擇添加遠程主機:
有了這款可視化工具,Java 應用性能調優 so easy。。。

3、輸入主機的名稱,直接寫ip,如下:

有了這款可視化工具,Java 應用性能調優 so easy。。。

右鍵新建的主機,選擇添加JMX連接,輸入在tomcat中配置的端口即可。

4、雙擊打開。完畢!


分享到:


相關文章: