內存問題錯綜復雜,本人水平也有限,淺薄之見僅供參考。
一、GC監控
GC日志記錄了內存使用和回收狀態,出現內存故障時,可作為分析排查手段。
1. 啟用GC監控的方法:增加java啟動參數-verbose:gc,輸出信息的樣例:
? GC?135:?total?final?references?4390;?cleared?final?references?8.?
GC?135:?total?phantom?references?0;?cleared?phantom?references?0.?
GC?135:?total?old?soft?references?0;?cleared?old?soft?references?0.?
GC?135:?total?JNI?global?weak?references?0;?cleared?JNI?global?weak?references?0.?
GC?136:?starting?collection,?maximum?allocation?reached.?
GC?136:?live?objects?1081046;?collected?objects?6038;?collected(KB)?558.?
GC?136:?queued?for?finalization?0;?total?soft?references?113;?cleared?soft?references?18.?
GC?136:?current?heap(KB)?716784;?current?threshold(KB)?262144.?
GC?136:?collect?(milliseconds)?1314.?
GC?136:?current?cycle?allocation(KB)?0;?previous?cycle?allocation(KB)?532.?
GC?136:?total?weak?references?1321;?cleared?weak?references?0.?
2. 將GC日志輸出到文件:不同JDK設置的參數不同,參考JDK官方文檔
?? SUN:-Xloggc:filename (例如:-Xloggc:D:/gc.log)
?? IBM:-Xverbosegc:file=filename 或 -Xverbosegclog:filename
?? HP?:-Xverbosegc=filename??
3. 如何設置Java啟動參數:有多種方式,以下各舉一例
?? Tomcat:在catalina.bat的“set JAVA_OPTS=%JAVA_OPTS% ”后設置
?? WebLogic:在startWebLogic.cmd的“%JAVA_HOME%\bin\java %JAVA_VM% %MEM_ARGS% %JAVA_OPTIONS% ”后設置
?? WebSphere:進入管理控制臺,應用服務器->進程定義->Java虛擬機高級定義
4. GC日志的圖形分析工具:HP的jtune

二、內存問題描述
典型現象是系統運行一段時間后,報OutOfMemoryError錯誤、頁面非常慢、不響應或完全不再接受請求,而此時通過觀察JVM內存,發現內存急劇上升到最大值并居高不下。
這種問題出現后,往往很棘手,通常是由于應用程序不合理造成的,而不合理程序或內存泄漏的源頭可能并不明顯。本人的一次經歷是,經過十多天各種測試手段后,最后確定問題是由一處String累加引起的,改成StringBuffer就解決了,可見,忽略“小問題”往往會帶來大麻煩。
三、分析手段
1. 分析GC日志、系統日志
2. 程序中設置監控斷點
3. 盡可能重現故障并同時監控JVM內存,找出引起內存急劇上升的規律
4. 檢查關鍵程序或頻繁使用的工具類的合理性
四、解決手段
1. 主要從程序入手:降低內存使用量;字符串累加時以StringBuffer代替String;隨時釋放不再需要的對象;SQL優化及避免頻繁取出大量數據;Session中不要放大的數據。。。
2. 據WebSphere和WebLogic官方建議:通常情況下JVM的Heap最小值和最大值可設成一樣(根據實際情況調整),可取系統內存的25%-75%,保證JVM有合理足夠的內存大小
3. 應用服務器的其他優化措施
五、應急措施
1. 不設定JVM的最大Heap上限
2. 程序中判斷內存吃緊時執行Runtime.gc()強制垃圾收集,此方式比自動收集徹底,可一定程度上改善內存利用效率
3. 在不影響業務的情況下,定期重啟應用服務器