GC overhead limt exceed檢查是Hotspot VM 1.6定義的一個策略,通過統計GC時間來預測是否要OOM了,提前拋出異常,防止OOM發生。Sun 官方對此的定義是:“并行/并發回收器在GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC并且回收了不到2%的堆內存。用來避免內存過小造成應用不能正常工作。
可以看到當堆中的對象無法被收回的時候,就提前遇警報出這樣的錯誤,此時內存并沒有溢出,這個特性在JDK中是默認添加的。
3、DUMP文件分析
將dump文件導入VisualVM工具中,如下圖所示:
通過上圖可以看出類結構圖中,最占用內存的是char[],LinkedHashMap和String三項。但是這三項的實例數并沒有占滿,看樣子不會內存溢出,怎么才能具體分析呢?原因就在于GC overhead limt exceed,這個錯并不會在內存真正溢出才會報,所以通過dump文件,我們只能自己去判斷分析,哪些項有可能會造成溢出,我們進入char[]項具體來看,會發現里面有很多hessian的url字符被緩存,通過排除程序可以看到由于底層中間件程序為了提高“性能”,將每次調用的url都緩存起來,不用每次都生成,但沒有相應緩存釋放操作,于是造成了大量字符對象長期持有從而報錯,在此就不截圖來具體看代碼,涉及一些公司信息。
4、問題解決方案
可以添加JVM的啟動參數來去掉提前報警限制:-XX:-UseGCOverheadLimit,于其讓應用每次都提前報警,還不如讓暴風雨來的更猛些,直接內存溢出,因為服務器是集群,其中一臺掛掉不會影響線上正常交易,同時也方便我們通過日志來排錯。
通過排查程序,檢查系統是否有使用大內存的代碼不釋放或死循環。
原文轉自:http://www.jianshu.com/p/6df2963fe94e