1. 程式人生 > >《JVM》(五)內存溢出異常與調優

《JVM》(五)內存溢出異常與調優

系統 dir 16px round 崩潰 -s 區域 ott 緩沖區

內存溢出異常

除了程序計數器之外,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》(五)內存溢出異常與調優