Code Cache (non-heap):HotSpot Java虛擬機包括一個用于編譯和保存本地代碼(native code)的內存,叫做“代碼緩存區”(code cache)
第三部分 監控(工具發現問題)
談到內存監控工具,JConsole是必須要介紹的,它是一個用JAVA寫的GUI程序,用來監控VM,并可監控遠程的VM,易用且功能強大。具體可監控JAVA內存、JAVA CPU使用率、線程執行情況、加載類概況等,Jconsole需要在JVM參數中配置端口才能使用。
由于是GUI程序,界面可視化,這里就不做詳細介紹,
具體幫助支持文檔請參閱性能測試JConsole使用方法總結:
http://www.taobao.ali.com/chanpin/km/test/DocLib/性能測試輔助工具-JConsole的使用方法.aspx
或者參考SUN官網的技術文檔:
http://Java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html
http://Java.sun.com/javase/6/docs/technotes/tools/share/jconsole.html
在實際測試某一個項目時,內存出現泄露現象。起初在性能測試的1個小時中,并不明顯,而在穩定性測試的時候才發現,應用的HSF調用在經過幾個小時運行后,就出現性能明顯下降的情況。在服務日志中報大量HSF超時,但所調用系統沒有任何超時日志,并且壓力應用的load都很低。經過查看日志后,認為應用可能存在內存泄漏。通過jconsole 以及 jmap 工具進行分析發現,確實存在內存泄漏問題,其中PS Old Gen最終達到占用 100%的占用。如圖所示:
從上圖可以看到,雖然每次Full GC,JVM內存會有部分回收,但回收并不徹底,不可回收的內存對象會越來越多,這樣便會出現以上的一個趨勢。在Full GC無法回收的對象越來越多時,最終已使用內存達到系統分配的內存最大值,系統最后無內存可分配,最終down機。
第四部分 分析
經過開發和架構師對應用的分析,查看此時內存隊列,看哪個對象占用數據最多,再利用jmap命令,對線程數據分析,如下所示:
num #instances #bytes class name
———————————————-
1: 9248056 665860032 com.taobao.matrix.mc.domain.**
2: 9248031 295936992 com.taobao.matrix.**
3: 9248068 147969088 java.util.**
4: 1542111 37010664 java.util.Date
前三個instances不斷增加,指代的是同一個代碼邏輯,異步分發的問題,堵塞消息,回收多次都無法回收成功。導致內存溢出。
此外,對應用的性能單獨做了壓測,他的性能只能支撐到一半左右,故發送消息的TPS,應用肯定無法處理過來,導致消息堆積,而JAVA垃圾回收期認為這些都是有用的對象,導致內存堆積,直至系統崩潰。
調優方法
由于具體調優方法涉及到應用的配置信息,故在此暫不列出,可以參考性能測試小組發布的《性能測試調優寶典》
第四部分 總結
內存溢出主要是由于代碼編寫時對某些方法、類應用不合理,或者沒有預估到臨時對象會占用很大內存量,或者把過多的數據放入JVM緩存,或者性能壓力大導致消息堆積而占用內存,以至于在性能測試時,生成龐大數量的臨時對象,GC時沒有做出有效回收甚至根本就不能回收,造成內存空間不足,內存溢出。
如果編碼之前,對內存使用量進行預估,對放在內存中的數據進行評估,保證有用的信息盡快釋放,無用的信息能夠被GC回收,這樣在一定程度上是可以避免內存溢出問題的。