《JVM》(五)內存溢出異常與調優
除了程序計數器之外,jvm的其他幾個運行時區域都存在著OOM異常的可能性
java堆溢出
對象數量達到最大堆的容量限制後
虛擬機棧和本地方法棧溢出
線程請求的棧深度大於虛擬機所允許的最大深度
虛擬機在擴展棧時無法申請到足夠的內存空間
方法區和運行時常量池溢出
生成大量的class的情況
JDK的可視化工具
JConsole:java監視與管理控制臺
概述;類;vm摘要;MBean;
內存(相當於jstat);
線程(相當於jstack);
VisualVM:多合一故障處理工具
顯示虛擬機進程以及進程的配置,環境信息(jps,jinfo)
監視應用程序的CPU,GC,堆,方法區以及線程的信息(jstat,jstack)
dump以及分析堆轉儲快照(jmap,jhat)
方法級的程序運行性能分析,找出被調用最多,運行時間最長的方法
離線程序快照
調優案例分析
1.高性能硬件上的程序部署策略
問題:將網站堆內存固定在12GB,網站不定期出現長時間失去響應的情況。
原因:失去響應是因為過大的堆內存,程序設計產生成批大對象,進入老年代,GC停頓導致的。
解決:給java虛擬機分配超大堆的前提是,把握程序的Full GC頻率控制得足夠低。
控制GC頻率的關鍵是不能有成批的,長時間生存的大對象產生,這樣才能保證老年代的穩定。
現階段64位jdk性能測試結果普遍低於32位jdk,多數人選擇使用若幹個32位虛擬機建立邏輯集群:
無session復制的親和式集群:均衡器按照一定的算法(一般根據sessionId分配)將一個固定的用戶請求永遠分配到固定的一個集群節點處理。
2.集群間同步導致的內存溢出
問題:親和式集群,節點間沒有session同步,需要有一些數據共享,使用JBossCache構建一個全局緩存。不定期出現多次內存溢出問題
原因:JBossCache 的缺陷。JBossCache在發送數據時有一個全局filter,把數據操作時間同步到所有的節點中,當網絡情況不滿足,重發數據在內存中不斷堆積
解決:需要被集群共享的數據,使用類似JBossCache的緩存框架同步時,可以讀操作頻繁,不能寫頻繁。
3.堆外內存導致的溢出錯誤
問題:GC並不頻繁,Eden區,surviver區,老年代以及永久代均表示壓力不大,但還是報錯內存溢出
原因:除了java堆和永久代,還有些區域會占用一定的內存:Direct Memory;線程堆棧;socket緩沖區...
4.服務器jvm進程崩潰
問題:使用了異步方式調用另一個系統的web服務,速度不對等,導致等待的socket連接越來越多,虛擬機崩潰
解決:將異步調用改為生產者/消費者的消息隊列實現
《JVM》(五)內存溢出異常與調優