Jvisualvm--JAVA性能分析工具

JDK自帶的JAVA性能分析工具它已經在你的JDK bin目錄裏了,只要你使用的是JDK1.6 Update7以後的版本。點擊一下jvisualvm.exe圖標它就能夠運行了。java

這裏是VisualVM 的官方網站:https://visualvm.dev.java.net,資料很全,同時提供VisualVM最近版本下載。c++

1.安裝

只要安裝JDK便可,運行jvisualvm.exe ,選擇【工具】——【插件】——【可用插件】程序員

 

wKiom1MZqv6gTLYOAAHQALi3EVQ254.jpg·web

2使用

2.1.遠程機器設置

要從遠程應用程序中檢索數據,須要在遠程 JVM 上運行 jstatd 實用程序。即要進行如下操做:算法

1)jdk 安裝目錄的bin目錄下新建文件jstatd.all.policy,文件內容爲:   數組

grant codebase "file:${java.home}/../lib/tools.jar" {tomcat

 

permission java.security.AllPermission;服務器

 

};app

 

2)再新建文件jstatd.sh ,文件內容爲:eclipse

./jstatd -J-Djava.security.policy=jstatd.all.policy

 

3)啓動jstat : nohup jstatd.sh & (默認啓動端口爲1099)

4)配置resin.conf,把如下注釋打開:

   <!-- no use args

     <jvm-arg>-Xdebug</jvm-arg>

     <jvm-arg>-Dcom.sun.management.jmxremote</jvm-arg>

 

2.2.添加遠程監控機器

wKioL1MZs6mSYFZyAAEP56Xo1Tw306.jpg

 

2.3.配置Jconsole

1)在應用的resin配置文件中加配置:

<jvm-arg>-Dcom.sun.management.jmxremote</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.port=9009</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.ssl=false</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.authenticate=false</jvm-arg>

2)選擇Tools菜單裏的Plugins菜單,點擊 'VisualVM-JConsole' 而後點擊'Install' 按鈕

3)安裝完畢後從新啓動VisualVm

4)配置JConsole頁籤,點擊'JConsole Plugins'按鈕

5)點擊'Add JAR/Folder'按鈕,

6)添加JDK_HOME/demo/management/JTop/JTop.jar

7)從新打開監控頁面,能夠看到JConsole正常工做

wKiom1MZs_mgO1XbAAJmd4w8Pqc594.jpg

2.4.遠程監控cpu使用狀況

點採樣器欄:

wKioL1MZs_HzhnGDAAGh15q1Mts787.jpg

點擊cpu,觀察到cpu使用情況,點擊snapshot,採起結果,能夠選擇查看方法、類或包的cpu使用狀況,使用spacer.gif工具能夠查找想要查看的方法、類或包:

wKioL1MZtBzBJoWQAAF75iFVDSA718.jpg

2.5.GC監控

1)選擇要監控的pid,查看GC狀況

wKioL1MZtFPBa-3qAAH24ueOTx8191.jpg

若是Old區滿了,每次回收都不多或者回收不了,說明GC有問題

2.6.遠程監控內存泄露、解決內存溢出問題

1)內存泄露、溢出的異同

同:都會致使應用程序運行出現問題,性能降低或掛起。

異:

v內存泄露是致使內存溢出的緣由之一;內存泄露積累起來將致使內存溢出。

v內存泄露能夠經過完善代碼來避免;內存溢出能夠經過調整配置來減小發生頻率,但沒法完全避免。

2)監測內存泄漏

·內存泄漏是指程序中間動態分配了內存,但在程序結束時沒有釋放這部份內存,從而形成那部份內存不可用的狀況,重啓計算機能夠解決,但也有可能再次發生內存泄露,內存泄露和硬件沒有關係,它是由軟件設計缺陷引發的。  

·內存泄漏能夠分爲4類:

a. 常發性內存泄漏。發生內存泄漏的代碼會被屢次執行到,每次被執行的時候都會致使一塊內存泄漏。

b.偶發性內存泄漏。發生內存泄漏的代碼只有在某些特定環境或操做過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。因此測試環境和測試方法對檢測內存泄漏相當重要。

c.一次性內存泄漏。發生內存泄漏的代碼只會被執行一次,或者因爲算法上的缺陷,致使總會有一塊僅且一塊內存發生泄漏。好比,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,因此內存泄漏只會發生一次。

d.隱式內存泄漏。程序在運行過程當中不停的分配內存,可是直到結束的時候才釋放內存。嚴格的說這裏並無發生內存泄漏,由於最終程序釋放了全部申請的內存。可是對於一個服務器程序,須要運行幾天,幾周甚至幾個月,不及時釋放內存也可能致使最終耗盡系統的全部內存。因此,咱們稱這類內存泄漏爲隱式內存泄漏。

3)Heap dump 分析

每隔一段時間給所檢測的java應用作一次heap dump

wKiom1MZtKTTJ5K3AABJbkv4_d4875.jpg

(或者在響應應用pid上鼠標右鍵heap dump)彈出如下提示框:

wKioL1MZtKaiSdicAAB6rwX6AqE541.jpg

在應用服務器將此文件下載到jvisual vm所在的機器上,file--load打開此文件,以下面三圖所示:

wKiom1MZtSiQgvHBAAF6Dw_4JBI844.jpg

wKioL1MZtQLDKyaOAAO9bvzBju0083.jpg

wKiom1MZtSixQ5WVAAGs96BTilg611.jpg

對比上面三個截圖,發現彷佛有個東西在急速飆升,仔細一看是這個對象:org.eclipse.swt.graphics.Image 在第一章圖中這個還沒排的上,第二次dump已經上升到5181個,第三次就是7845個了。漲速至關快,並且和任務管理器裏面看到的GDI數量增漲一致,就是它了

問題到這兒就比較清楚了,回到代碼裏面仔細一看能夠發現,是某個地方反覆的用圖片來建立Image對象致使的,改掉之後搞定問題。

到這裏其實我想說的是,Java使用起來其實要比C++更容易致使內存泄漏。對於C++來講,每個申請的對象都必須明確釋放,任何沒有釋放的對象都會致使memleak,這是不可饒恕的,並且這類問題已經有不少工具和方法來解決。可是到了Java裏面狀況就不一樣了,對於Java程序員來講對象都是不須要也沒法主動銷燬的,因此通常的思路是:隨用隨new,用完即丟。不少對象具體的生命週期可能連寫代碼的人本身也不清楚,或者不須要清楚,只知道某個時刻垃圾收集器會去作的,不用管。但極可能某個對象在用完即丟的時候在另外一個不容易發現的地方被保存了一個引用,那麼這個對象就永遠不會被回收。更加糟糕的是整個程序從設計之初就沒有考慮過對象回收的問題,對於C++程序員來講memleak必然是一個設計錯誤,可是對Java程序員來講這只是一個疏忽,並且彷佛沒有什麼好的辦法來避免。今天看到的這個問題是由於GDI泄漏會形成嚴重後果才被重視,但若是僅僅是形成內存泄漏,那這個程序可能得連續跑上個十天半個月纔會發現問題。最後就是,對於c++,錯誤的代碼在測試階段就能夠快速的偵測出哪怕一個byte的memleak並加以改正,可是對於java程序,理論上沒有哪一個工具可以知道是否是有泄漏,由於除了做者本身之外沒有人可以知道一個被引用的對象是否是應該被銷燬,只有經過大量的,長期的壓力測試才能發現問題,這是很危險的一件事情。

4)解決內存溢出問題

一、java.lang.OutOfMemoryError: PermGen space

JVM管理兩種類型的內存,堆和非堆。堆是在JVM啓動時建立;非堆是留給JVM本身用的,用來存放類的信息的。它和堆不一樣,運行期內GC不會釋放空間。若是web app用了大量的第三方jar或者應用有太多的class文件而剛好MaxPermSize設置較小,超出了也會致使這塊內存的佔用過多形成溢出,或者tomcat熱部署時侯不會清理前面加載的環境,只會將context更改成新部署的,非堆存的內容就會愈來愈多。

PermGen space的全稱是Permanent Generation space是指內存的永久保存區域,這塊內存主要是被JVM存放Class和Meta信息的Class在被Loader時就會被放到PermGen space中,它和存放類實例(Instance)的Heap區域不一樣GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,因此若是你的應用中有很CLASS的話就極可能出現PermGen space錯誤,這種錯誤常見在web服務器對JSP進行pre compile的時候。若是你的WEB APP下都用了大量的第三方jar, 其大小超過了jvm默認的大小(4M)那麼就會產生此錯誤信息了。

wKioL1MZtlHREhrhAAMFKXoTEMw761.jpg

如上圖所示,PermGen在程序運行一段時間後超出了咱們指定的128MB,經過Classes視圖看到,Java在運行的同時加載了大量的類到內存中。PermGen會存儲Jar或者Class的描述信息;因此在class大量增長的同時PermGen超出了咱們指定的範圍。爲了讓應用穩定,咱們須要探尋新的PermGen範圍。檢測時段時候後(以下圖)發現PermGen145MB左右穩定,那麼咱們就獲得了穩定的新參數;這樣PermGen內存溢出的問題獲得解決。

wKiom1MZtrWRVGIQAAMV1WiIwr0717.jpg

 

二、java.lang.OutOfMemoryError: Java heap space

第一種狀況是個補充,主要存在問題就是出如今這個狀況中。其默認空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。若是內存剩餘不到40%,JVM就會增大堆到Xmx設置的值,內存剩餘超過70%,JVM就會減少堆到Xms設置的值。因此服務器的Xmx和Xms設置通常應該設置相同避免每次GC後都要調整虛擬機堆的大小。假設物理內存無限大,那麼JVM內存的最大值跟操做系統有關,通常32位機是1.5g到3g之間,而64位的就不會有限制了。

注意:若是Xms超過了Xmx值,或者堆最大值和非堆最大值的總和超過了物理內存或者操做系統的最大限制都會引發服務器啓動不起來。

 

垃圾回收GC的角色JVM調用GC的頻度仍是很高的,主要兩種狀況下進行垃圾回收:

一個是當應用程序線程空閒;另外一個是java內存堆不足時,會不斷調用GC,若連續回收都解決不了內存堆不足的問題時,就會報out of memory錯誤。由於這個異常根據系統運行環境決定,因此沒法預期它什麼時候出現。

根據GC的機制,程序的運行會引發系統運行環境的變化,增長GC的觸發機會。

爲了不這些問題,程序的設計和編寫就應避免垃圾對象的內存佔用和GC的開銷。顯示調用System.GC()只能建議JVM須要在內存中對垃圾對象進行回收,但不是必須立刻回收一個是並不能解決內存資源耗空的局面,另外也會增長GC的消耗。

wKiom1MZuOfBZE4hAAJS5vcnocE082.jpg

 

2.7.如何避免內存泄漏、溢出

1)儘早釋放無用對象的引用。

好的辦法是使用臨時變量的時候,讓引用變量在退出活動域後自動設置爲null,暗示垃圾收集器來收集該對象,防止發生內存泄露。

2) 程序進行字符串處理時,儘可能避免使用String,而應使用StringBuffer。

由於每個String對象都會獨立佔用內存一塊區域,如:

1.String str = "aaa";    

2.String str2 = "bbb";    

3.String str3 = str + str2;    

4.// 假如執行這次以後str , str2再不被調用,那麼它們就會在內存中等待GC回收;    

5.// 假如程序中存在過多的相似狀況就會出現內存錯誤;  

3) 儘可能少用靜態變量。

由於靜態變量是全局的,GC不會回收。

4) 避免集中建立對象尤爲是大對象,若是能夠的話儘可能使用流操做。

JVM會忽然須要大量內存,這時會觸發GC優化系統內存環境; 一個案例以下:

1.// 使用jspsmartUpload做文件上傳,運行過程當中常常出現java.outofMemoryError的錯誤,    

2.// 檢查以後發現問題:組件裏的代碼    

3.m_totalBytes = m_request.getContentLength();    

4.m_binArray = new byte[m_totalBytes];    

5.// totalBytes這個變量獲得的數極大,致使該數組分配了不少內存空間,並且該數組不能及時釋放。    

6.// 解決辦法只能換一種更合適的辦法,至少是不會引起outofMemoryError的方式解決。    

7.// 參考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747  

5) 儘可能運用對象池技術以提升系統性能。

生命週期長的對象擁有生命週期短的對象時容易引起內存泄漏,例如大集合對象擁有大數據量的業務對象的時候,能夠考慮分塊進行處理,而後解決一塊釋放一塊的策略。

6) 不要在常常調用的方法中建立對象,尤爲是忌諱在循環中建立對象。

能夠適當的使用hashtable,vector 建立一組對象容器,而後從容器中去取那些對象,而不用每次new以後又丟棄。

7) 優化配置。

a.設置-Xms、-Xmx相等;

b.設置NewSize、MaxNewSize相等;

c.設置Heap size, PermGen space:

相關文章
相關標籤/搜索