JVM內存狀況查看方法和分析工具


http://www.cnblogs.com/panxuejun/p/6052292.html

Java本身提供了多種豐富的方法和工具來幫助開發人員查看和分析GC及JVM內存的狀況,同時開源界和商業界也有一些工具可用於查看、分析GC及JVM內存的狀況。通過這些分析,可以排查程序中內存泄露的問題及調優程序的性能。下面介紹幾種常用的免費工具,其中知名的有JProfiler 等。

 

  1. 輸出GC日志

 

  輸出GC日志對於跟蹤分析GC的狀況來說,無疑是最直接地分析內存回收狀況的方法,只是GC日志輸出后需要人為地進行分析,以判斷GC的狀況。

 

  JVM支持將日志輸出到控制台或指定的文件中,方法有如下幾種。

 

  輸出到控制台

 

  在JVM的啟動參數中加入-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime,按照參數的順序分別輸出GC的簡要信息,GC的詳細信息、GC的時間信息及GC造成的應用暫停的時間。

 

  輸出到指定的文件

 

  在1中的jvm啟動參數中再增加-Xloggc: gc.log可指定將gc的信息輸出到gc.log中。

 

  可用於GC跟蹤分析的參數還有-verbose:gc、-XX:+PrintTenuringDistribution等。

 

  2. GC Portal

 

  將GC日志輸出固然有一定的作用,但如果要靠人為進行分析,還是相當復雜的。因此Sun提供了一個GC Portal來幫助分析這些GC日志,並生成相關的圖形化的報表,GC Portal部署起來會有些麻煩,它需要運行在老版本的Tomcat上,同時需要數據庫,部署完畢后通過上傳日志文件的方式即可完成GC日志的分析,此GC日志輸出的JVM參數為:-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps [-Xloggc:文件名],在上傳日志時GC Portal的選項里只有jdk 1.2或jdk 1.2-1.4的版本。雖然經過測試,JDK 6的日志也是可以分析出來的,但它的限制在於僅支持5MB的gc日志的分析,GC Portal可提供吞吐量的分析、耗費的CPU的時間、造成的應用暫停的時間、每秒從新生代轉化到舊生代的數量、minor GC的狀況及Full GC的狀況等,如圖1所示。

 

 

圖1  GCPortal示例

 

  GC Portal中還有一個很有用的部分是提供調整GC參數的預測,例如可以選擇給young size增加20%的空間。GC Portal會根據當前的日志信息來評估在調整參數后的運行效果,不一定很准確,但畢竟能帶來一些參考意義。

 

 

 

3. JConsole

 

  JConsole可以圖形化查看JVM中內存的變化狀況,JConsole是JDK 5及以上版本中自帶的工具,位於JDK的bin目錄下,運行時直接運行JConsole.exe或JConsole.sh(要求支持圖形界面)。在本地的Tab頁上看到運行了java的pid,雙擊即可查看相應進程的JVM狀況,同時,JConsole也支持查看遠程的JVM的運行狀況,具體可參見JConsole的User Guide。

 

  JConsole中顯示了JVM中很多的信息:內存、線程、類和MBean等,在打開JConsole的內存Tab頁后,可看到JVM內存部分的運行狀況。這對於分析內存是否有溢出及GC的效果更加直接明了,JConsole的運行效果如圖2所示。

 

 

圖2  JConsole運行效果

 

  4. JVisualVM

 

  JVisualVM是JDK 6 update 7之后推出的一個工具,它類似於JProfiler的工具,基於此工具可查看內存的消耗情況、線程的執行狀況及程序中消耗CPU、內存的動作。

 

  在內存分析上,JVisualVM的最大好處是可通過安裝VisualGC插件來分析GC趨勢、內存消耗詳細狀況。

 

  VisualGC的運行如圖3所示。

 

 

圖3  VisualGC運行效果

 

  從圖3中可看到各區的內存消耗狀況及GC Time的圖表,其提供的Histogram視圖對於調優也有很大幫助。

 

  基於JVisualVM的Profiler中的Memory還可查看對象占用內存的狀況,如圖4所示。

 

4. JMap

 

  JMap是JDK中自帶的一個用於分析JVM內存狀況的工具,位於JDK的bin目錄下。使用JMap可查看目前JVM中各個代的內存狀況、JVM中對象的內存的占用狀況,以及導出整個JVM中的內存信息。

 

 

圖4  JVisualVM Memory Profiler圖示

 

  查看JVM中各個代的內存狀況

 

  在linux上執行jmap -heap [pid],就可查看整個JVM中內存的狀況,看到的信息類似如下(和JDK版本、GC策略有關):

 

 

 

using thread-local object allocation.  Parallel GC with 8 thread(s)  Heap Configuration:     MinHeapFreeRatio = 40    MaxHeapFreeRatio = 70    MaxHeapSize      = 1610612736 (1536.0MB)     NewSize          = 524288000 (500.0MB)     MaxNewSize       = 524288000 (500.0MB)     OldSize          = 4194304 (4.0MB)     NewRatio         = 8    SurvivorRatio    = 8    PermSize         = 100663296 (96.0MB)     MaxPermSize      = 268435456 (256.0MB)  Heap Usage:  PS Young Generation  Eden Space:     capacity = 430702592 (410.75MB)     used     = 324439936 (309.4100341796875MB)     free     = 106262656 (101.3399658203125MB)     75.32806675098904% used  From Space:     capacity = 46333952 (44.1875MB)     used     = 13016424 (12.413429260253906MB)     free     = 33317528 (31.774070739746094MB)     28.092626331550566% used  To Space:     capacity = 46792704 (44.625MB)     used     = 0 (0.0MB)     free     = 46792704 (44.625MB)     0.0% used  PS Old Generation     capacity = 1086324736 (1036.0MB)     used     = 945707880 (901.8973159790039MB)     free     = 140616856 (134.1026840209961MB)     87.05572548059884% used  PS Perm Generation     capacity = 100663296 (96.0MB)     used     = 46349592 (44.202415466308594MB)     free     = 54313704 (51.797584533691406MB)     46.044182777404785% used

 

 

從以上信息中可看出JVM堆的配置信息,如NewSize、NewRatio、SurvivorRatio等;JVM堆的使用情況,新生代中的Eden Space、From Space、To Space的使用情況,舊生代和持久代的使用情況。

  要注意的是在使用CMS GC的情況下,jmap -heap的執行有可能會導致Java進程被掛起。

 

  JVM中對象的內存的占用情況

 

  在查看JVM內存狀況時,除了要知道每個代的占用情況外,很多時候更要知道其中各個對象占用的內存大小,這樣便於分析對象的內存占用情況,在分析OutOfMemory的場景中尤其適用。

 

  輸入jmap -histo [pid]即可查看jvm堆中對象的詳細占用情況,如圖1所示。

 

 

圖1  jmap -histo運行效果

 

  輸出內容按照占用空間的大小排序,例如上面的[C,表示char類型的對象在jvm中總共有243 707個實例,占用了501 638 784 bytes的空間。

 

  導出整個JVM中的內存信息

 

  通過以上方法能查看到JVM中對象內存的占用情況,但很多時候還要知道這個對象到底是誰創建的。例如上面顯示出來的[C,只知道它占用了那么多的空間,但不知道是什么對象創建出的[C,於是jmap提供了導出整個jvm中的內存信息的支持。基於一些jvm內存的分析工具,例如sun JDK 6中的jhat、Eclipse Memory Analyzer,可以分析jvm中內存的詳細信息,例如[C是哪些對象創建的。

 

  執行如下命令即可導出整個jvm中的內存信息:

 

 

 

jmap -dump:format=b,file=文件名 [pid]

 

 

 

  5. JHat

 

  JHat是Sun JDK 6及以上版本中自帶的一個用於分析jvm堆dump文件的工具,基於此工具可分析jvm heap中對象的內存占用狀況、引用關系等。

 

  執行如下命令分析jvm堆的dump文件:

 

 

 

jhat -J-Xmx1024M [file]

 

 

 

  執行后等待console中輸出Started HTTP server on port 7000,看到后就可以通過瀏覽器訪問http://ip:7000了,此頁面默認為按package分類顯示系統中所有的對象實例。在頁面的最下端有Other Queries導航,其中有顯示jvm中對象實例個數的鏈接、有顯示jvm中對象大小的鏈接等,點擊顯示jvm中對象大小的鏈接,得到的結果如圖2所示。

 

 

圖2  jhat運行效果

 

  點擊圖2中的class [C,可以看到有哪些對象實例引用了這個對象,或者創建了這個對象,jhat在分析大的堆dump文件時表現不好,速度很慢。

 

6. JStat

 

  JStat是Sun JDK自帶的一個統計分析JVM運行狀況的工具,位於JDK的bin目錄下,除了可用於分析GC的狀況外,還可用於分析編譯的狀況、class加載的狀況等。

 

  JStat用於GC分析的參數有:-gc、-gccapacity、-gccause、-gcnew、-gcnewcapacity、-gcold、-gcoldcapacity、-gcpermcapacity、-gcutil。常用的為-gcutil。通過-gcutil可按一定頻率查看jvm中各代的空間的占用情況、minor GC的次數、消耗的時間、full GC的次數及消耗的時間的統計,執行jstat -gcutil [pid] [interval],可看到類似如下的輸出信息:

 

 

 

 S0     S1       E      O       P       YGC   
YGCT     FGC    FGCT     GCT   0.00   74.24  96.73  73.43  46.05  17808  
382.335   208  315.197  697.533  45.37   0.00   28.12  74.97  46.05  17809 
382.370   208  315.197  697.568

 

 

 

  其中S0、S1就是Survivor空間的使用率,E表示Eden空間的使用率,O表示舊生代空間的使用率,P表示持久代的使用率,YGC表示minor GC的執行次數,YGCT表示minor GC執行消耗的時間,FGC表示Full GC的執行次數,FGCT表示Full GC執行消耗的時間,GCT表示Minor GC+Full GC執行消耗的時間。

 

  7. Eclipse Memory Analyzer

 

  Eclipse Memory Analyzer是Eclipse提供的一個用於分析jvm堆dump文件的插件,借助這個插件可查看對象的內存占用狀況、引用關系、分析內存泄露等。

 

  Eclipse Memory Analyzer(MAT)的網站為:http://www.eclipse.org/mat/,在eclipse中可以直接遠程安裝此插件。不過由於此插件在分析堆dump文件時比較耗內存,因此在分析前最好先將eclipse的jvm的內存設置大一點,MAT分析dump文件后的對象占用內存及引用關系如圖3所示。

 

  相對而言MAT功能比jhat強大很多,分析的速度也快一些,因此,如果要分析jvm堆dumap文件,首選推薦的是MAT。

 

  在進行JVM內存狀況分析時,通常要關注的主要有GC的趨勢、內存的具體消耗狀況。

 

  GC趨勢對於可圖形界面連到需查看GC狀況的機器的情況而言,VisualVM是常用的選擇;對於不能采用圖形界面方式的,輸出GC日志 及采用jstat命令直接分析是常用的選擇。

 

  在查找內存是程序中的什么對象占用時,需要分析內存的具體消耗狀況,對於有圖形界面可用的情況,VisualVM是常用的選擇;對於不能采用圖形界面方式的,可通過jmap dump生成文件后,再通過MAT進行分析是常用的選擇。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM