如何在JVM內存溢出的時候自動dump內存快照


解決OOM問題的一個初步思路

首先第一個問題,假設發生OOM了,必然說明系統中某個區域的對象太多了,塞滿了那個區域,而且一定是無法回收掉那些對象,最終才會導致內存溢出的。

既然是這個思路,要解決OOM的話,首先就得知道到底是什么對象太多了最終導致OOM的?

所以你想知道什么對象太多導致OOM的,就必須得有一份JVM發生OOM時的dump內存快照

只要有了那個dump內存快照,你就可以用之前介紹過的MAT之類的工具瞬間分析得到什么對象太多了。

那么現在一個關鍵問題來了,到底怎么做才可以在JVM內存溢出的時候自動dump出來一份內存快照呢?

在OOM的時候自動dump內存快照

看到這里,大家必須得對一個事情有個概念,大家可以思考一下,假設JVM發生OOM了,你覺得JVM是完全來不及處理然后突然進程就沒了嗎?也就是JVM是看起來非常突然的自己無法控制的就掛掉了嗎?

其實不是的,只要之前對JVM OOM的各種情況原理有一定的了解,就會知道JVM本身在發生OOM之前都會盡可能的去進行GC騰出來一些內存空間

如果GC后還是沒有空間,放不下對象, 才會觸發內存溢出的。

所以JVM自己對OOM情況的發生是完全有把控權的,他知道什么時候會觸發OOM,也是他自己感覺不行的時候才會去觸發的

所以OOM的發生並不是大家想的那樣,突然之間內存太多了,JVM自己都沒反應過來就直接崩潰了,並非如此。

因此JVM如果知道要發生OOM了,此時完全可以讓他做點事情

我們可以讓他在OOM時dump一份內存快照,事后我們只要分析這個內存快照,一下就可以知道是哪些可惡的對象占用了所有的內存,並且還無法釋放。

此時你就需要在JVM的啟動參數中加入如下的一些參數:

-XX:+HeapDumpOnOutOfMemoryError  
-XX:HeapDumpPath=/usr/local/app/oom

第一個參數意思是在OOM的時候自動dump內存快照出來,第二個參數是說把內存快照放到哪兒去

只要你加入了這兩個參數,在JVM OOM崩潰的時候,無論你是立馬主動收到一個報警,還是被動讓客服通知了你,立馬就可以去找OOM時候的內存快照了。

迄今為止我們可以得出的一份JVM參數模板

在學習完這篇文章之后,我們最常用的一些JVM參數已經全部學習完了,而且可以總結一份JVM參數模板出來供大家進行參考,大家未來對自己的系統只要根據自己的情況去調整就可以了:

-Xms4096M -Xmx4096M -Xmn3072M -Xss1M  -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M 
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 
-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 
-XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark 
-XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:gc.log 
-XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=/usr/local/app/oom

這份JVM參數模板基本上涵蓋了所有你需要的一些參數

首先是各個內存區域的大小分配,這個是需要你精心調優的

其次是兩種垃圾回收器的指定,接着是一些常規性的CMS垃圾回收的參數,可以幫助優化偶爾發生的Full GC性能。

最重要的就是平時要打印出來GC日志,GC日志可以配合你用jstat工具分析GC頻率和性能的時候用,jstat可以分析出來GC的頻率,但是對每次具體的GC情況,可以結合GC日志來看。

還有就是在OOM的時候需要自動dump內存快照,這樣即使突然發生OOM,你只要得知了這個事,立馬就可以去分析內存快照了。

同時結合GC日志,讓大家更加清晰的理解每次發生內存溢出時候的具體過程和原理,以及解決內存溢出的排查過程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM