1. 程式人生 > >JVM的OOM分析總結

JVM的OOM分析總結

修飾 rec 大於 工具 找到 ant 最大值 類型信息 時間

一、heap堆內存溢出可以分為兩種情況:
1、內存泄漏(Memory Leak)
如果是內存泄漏,可以進一步通過工具查看泄漏對象到GC ROOTS的引用鏈。於是就能找到泄漏對象是通過怎麽樣的路徑與GC Roots相關聯並導致垃圾收集器無法自動回收他們的。掌握了泄漏對象的類型信息及GC Roots引用鏈的信息,就可以比較準確地定位出泄漏代碼的位置。
2、內存溢出(Memory overflow)
如果不是內存泄漏,換句話說,就是內存中的對象確實都還必須活著,那就應當檢查虛擬機的堆參數(-Xmx 與 -Xms),與機器物理內存對比看是否還可以調大,從代碼上檢查是否存在某些對象生命周期過長、持有狀態時間過長的情況,嘗試減少程序運行期的內存消耗。

二、棧內存溢出(-Xss):
1、如果線程請求的深度大於虛擬機所允許的最大深度,將拋出StackOverflowError異常。如果棧的深度小或者棧針的容量比較大、用遞歸時,都可能引起。
2、如果是虛擬機在擴展時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常。當使用多線程的時候,需要註意。

三、方法區和運行時常量池溢出(-XX:PermSize -XX:MaxPermSize)
運行時常量池:運行時常量池是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述外,還有一項信息是常量池(Constant Pool TABLE),用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後進入方法區的運行時常量池中存放。一般來說,除了保存Class文件中描述的符號引用外,還會把翻譯出來的直接引用也存儲在運行時常量池中。方法區限定大小後,就間接的限制其中常量池的容量。
1、常量池中存放大量的String對象,並保持對這些對象的引用,避免Full GC回收常量池,就會產生OutOfMemoryError異常,後面跟的提示信息是“PermGen space”,說明運行時常量池屬於方法區。
2、方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。當產生大量的類去填充滿方法區,就會溢出

四、本機直接內存溢出(-MaxDirectMemorySize):
DirectMemory容量可通過MaxDirectMemorySize指定,如果不指定,則默認與java堆最大值一樣。雖然DirectMemory內存溢出時也會拋出內存溢出異常,但它拋出的異常時並沒有真正向操作系統申請內存分配,於是手動拋出異常。一個明顯的特征是在Heap Dump文件中不會看見明顯的異常,如果發現OOM之後Dump文件很小,而且程序中又直接或者間接使用了NIO,那就可以考慮檢查一下是不是這方面的原因。

如果有不同見解,可以多多交流!

JVM的OOM分析總結