小A:xx服務又宕機了java
小B:歪日,咋搞的,登上去看看咋回事web
小A:又OOM了,不知道哪一個**寫的代碼,一坨*同樣。數組
擼Java的同窗,多多少少會碰到內存溢出(OOM)的場景,但形成OOM的緣由倒是多種多樣。tomcat
堆溢出app
這種場景最爲常見,報錯信息:框架
java.lang.OutOfMemoryError: Java heap space
緣由less
一、代碼中可能存在大對象分配ide
二、可能存在內存泄露,致使在屢次GC以後,仍是沒法找到一塊足夠大的內存容納當前對象。工具
解決方法優化
一、檢查是否存在大對象的分配,最有可能的是大數組分配
二、經過jmap命令,把堆內存dump下來,使用mat工具分析一下,檢查是否存在內存泄露的問題
三、若是沒有找到明顯的內存泄露,使用 -Xmx 加大堆內存
四、還有一點容易被忽略,檢查是否有大量的自定義的 Finalizable 對象,也有多是框架內部提供的,考慮其存在的必要性
永久代/元空間溢出
報錯信息:
java.lang.OutOfMemoryError: PermGen space java.lang.OutOfMemoryError: Metaspace
緣由
永久代是 HotSot 虛擬機對方法區的具體實現,存放了被虛擬機加載的類信息、常量、靜態變量、JIT編譯後的代碼等。
JDK8後,元空間替換了永久代,元空間使用的是本地內存,還有其它細節變化:
字符串常量由永久代轉移到堆中
和永久代相關的JVM參數已移除
可能緣由有以下幾種:
一、在Java7以前,頻繁的錯誤使用String.intern()方法
二、運行期間生成了大量的代理類,致使方法區被撐爆,沒法卸載
三、應用長時間運行,沒有重啓
沒有重啓 JVM 進程通常發生在調試時,以下面 tomcat 官網的一個 FAQ:
Why does the memory usage increase when I redeploy a web application?
That is because your web application has a memory leak.
A common issue are 「PermGen」 memory leaks. They happen because the Classloader (and the Class objects it loaded) cannot be recycled unless some requirements are met (). They are stored in the permanent heap generation by the JVM, and when you redeploy a new class loader is created, which loads another copy of all these classes. This can cause OufOfMemoryErrors eventually.
(*) The requirement is that all classes loaded by this classloader should be able to be gc’ed at the same time.
解決方法
由於該OOM緣由比較簡單,解決方法有以下幾種:
一、檢查是否永久代空間或者元空間設置的太小
二、檢查代碼中是否存在大量的反射操做
三、dump以後經過mat檢查是否存在大量因爲反射生成的代理類
四、放大招,重啓JVM
GC overhead limit exceeded
這個異常比較的罕見,報錯信息:
java.lang.OutOfMemoryError:GC overhead limit exceeded
緣由
這個是JDK6新加的錯誤類型,通常都是堆過小致使的。Sun 官方對此的定義:超過98%的時間用來作GC而且回收了不到2%的堆內存時會拋出此異常。
解決方法
一、檢查項目中是否有大量的死循環或有使用大內存的代碼,優化代碼。
二、添加參數 -XX:-UseGCOverheadLimit 禁用這個檢查,其實這個參數解決不了內存問題,只是把錯誤的信息延後,最終出現 java.lang.OutOfMemoryError: Java heap space。
三、dump內存,檢查是否存在內存泄露,若是沒有,加大內存。
方法棧溢出
報錯信息:
java.lang.OutOfMemoryError : unable to create new native Thread
緣由
出現這種異常,基本上都是建立的了大量的線程致使的,之前碰到過一次,經過jstack出來一共8000多個線程。
解決方法
一、經過 -Xss 下降的每一個線程棧大小的容量
二、線程總數也受到系統空閒內存和操做系統的限制,檢查是否該系統下有此限制:
/proc/sys/kernel/pid_max
/proc/sys/kernel/thread-max
maxuserprocess(ulimit -u)
/proc/sys/vm/maxmapcount
很是規溢出
下面這些OOM異常,可能大部分的同窗都沒有碰到過,但仍是須要了解一下
分配超大數組
報錯信息 :
java.lang.OutOfMemoryError : Requested array size exceeds VM limit
這種狀況通常是因爲不合理的數組分配請求致使的,在爲數組分配內存以前,JVM 會執行一項檢查。要分配的數組在該平臺是否能夠尋址(addressable),若是不能尋址(addressable)就會拋出這個錯誤。
解決方法就是檢查你的代碼中是否有建立超大數組的地方。
swap溢出
報錯信息 :
java.lang.OutOfMemoryError : Out of swap space
這種狀況通常是操做系統致使的,可能的緣由有:
一、swap 分區大小分配不足;
二、其餘進程消耗了全部的內存。
解決方案:
一、其它服務進程能夠選擇性的拆分出去
二、加大swap分區大小,或者加大機器內存大小
本地方法溢出
報錯信息 :
java.lang.OutOfMemoryError: stack_trace_with_native_method
本地方法在運行時出現了內存分配失敗,和以前的方法棧溢出不一樣,方法棧溢出發生在 JVM 代碼層面,而本地方法溢出發生在JNI代碼或本地方法處。
這個異常出現的機率極低,只能經過操做系統本地工具進行診斷,難度有點大,仍是放棄爲妙。