實戰Java虛擬機:JVM故障診斷與性能優化》第7章分析Java堆,本章主要介紹了Java堆的分析方法。首先,介紹了幾種常見的Java內存溢出現象及解決思路。其次,探討了java.lang.String類的特色,以及在JDK 1.6和JDK 1.7中的改進與區別。本節爲你們介紹Tomcat堆溢出分析。java
7.3.5 Tomcat堆溢出分析(1)性能優化
Tomcat是最經常使用的Java Servlet容器之一,同時也能夠當作單獨的Web服務器使用。Tomcat自己使用Java實現,並運行於Java虛擬機之上。在大規模請求時,Tomcat有可能會由於沒法承受壓力而發生內存溢出錯誤。本節根據一個被壓垮的Tomcat的堆快照文件,來分析Tomcat在崩潰時的內部狀況。服務器
圖7.22顯示了Tomcat溢出時的整體信息,能夠看到堆的大小爲29.7MB。從統計餅圖中得知,當前深堆最大的對象爲StandardManager,它持有大約16.4MB的對象。session
通常來講,咱們老是會對佔用空間最大的對象特別感興趣,若是能夠查看StandardManager內部究竟引用了哪些對象,對於分析問題可能會起到很大的幫助。所以,在餅圖中單擊StandardManager所在區域,在彈出菜單中選擇「with outgoing references」命令,如圖7.23所示。這樣將會列出被StandardManager引用的全部對象。性能
圖7.24顯示了被StandardManager引用的對象,其中特別顯眼的就是sessions對象,它佔用了約17MB空間。優化
繼續查找,打開sessions對象,查看被它引用的對象,如圖7.25所示。能夠看到sessions對象爲ConcurrentHashMap,其內部分爲16個Segment。從深堆大小看,每一個Segment都比較平均,大約爲1MB,合計17MB。3d
繼續打開Segment,查看存儲在sessions中的真實對象。如圖7.26所示,能夠找到內部存放的爲StandardSession對象。htm
7.3.5 Tomcat堆溢出分析(2)對象
經過OQL命令,查找全部的StardardSession,如圖7.27所示(有關OQL,請參閱7.4節)。能夠看到當前堆中含有9941個session,而且每個session的深堆爲1592字節,合計約15MB,達到當前堆大小的50%。由此,能夠知道,當前Tomcat發生內存溢出的緣由,很可能是因爲在短時間內接收大量不一樣客戶端的請求,從而建立大量session致使。blog
爲了得到更爲精確的信息,能夠查看每個session的內部數據,如圖7.28所示,在左側的對象屬性表中,能夠看到所選中的session的最後訪問時間和建立時間。
經過OQL命令和MAT的排序功能,如圖7.29所示,能夠找到當前系統中最先建立的session和最後建立的session。再根據當前的session總數,能夠計算每秒的平均壓力爲:9941/(1403324677648-1403324645728)*1000=311次/秒。
由此推斷,在發生Tomcat堆溢出時,Tomcat在連續30秒的時間內,平均每秒接收了約311次不一樣客戶端的請求,建立了合計9941個session。