常见的Java内存溢出情况和实例
文章目錄
- 內存溢出的原因
- 棧溢出
- 棧溢出的第1種情況,死遞歸,拋出StackOverflowError
- 棧溢出的第2種情況,線程太多,拋出OutOfMemoryError
- 堆溢出
- 1.初始對象太大,超過機器內存,拋出OutOfMemoryError: Java heap space
- 2.在方法執行中,回收效率不足2%,拋出OutOfMemoryError: GC overhead limit exceeded
- 直接內存溢出 Direct buffer memory
- 方法區溢出java.lang.OutOfMemoryError: Metaspace
Java開發中或者部署到服務器上后,可能經常發生內存溢出,本文總結下常見的溢出情況。
內存溢出的原因
Java內存溢出的原因:程序在申請內存時,沒有足夠的內存空間.
內存溢出有幾種類型,如下:
棧溢出
棧溢出的第1種情況,死遞歸,拋出StackOverflowError
如下代碼:
public class StackOverFlow {public void test(){test();//死遞歸}public static void main(String[] args)throws Throwable {StackOverFlow javaStack = new StackOverFlow();javaStack.test();} }運行后發生如下異常:
Exception in thread “main” java.lang.StackOverflowError
at com.jvm.ch05.oom.StackOverFlow.test(StackOverFlow.java:13)
at com.jvm.ch05.oom.StackOverFlow.test(StackOverFlow.java:13)
在java虛擬機種,Java的??臻g默認是1M大小(可以通過-Xss調整,一般不用調整),反復調用,會超出棧溢出。
棧溢出的第2種情況,線程太多,拋出OutOfMemoryError
如果1個方法運行中的對象占用1M內存。同時5000+個線程運行這個方法,如果機器的內存小于5G的話,那么也會發生內存溢出,這種情況會拋出OOM異常。
堆溢出
1.初始對象太大,超過機器內存,拋出OutOfMemoryError: Java heap space
如下代碼:
//VM Args:-Xms30m -Xmx30m -XX:+PrintGCDetails 堆的大小30M String[] strings = new String[100000000]; //100m的數組(堆)運行結果:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at com.jvm.ch05.oom.HeapOom.main(HeapOom.java:14)
對象分配內存需要100M.如果機器的內存小于100M就會發生 Java heap space。
2.在方法執行中,回收效率不足2%,拋出OutOfMemoryError: GC overhead limit exceeded
demo如下:
/**** VM Args:-Xms10m -Xmx10m -Xmn5m -XX:+PrintGCDetails 堆的大小10M* 堆內存溢出*/ public class HeapOom {public static void main(String[] args){List<Object> list = new LinkedList<>(); //在方法執行的過程中,它是GCRootsint i =0;while(true){i++;if(i%10000==0) System.out.println("i="+i);list.add(new Object());}} }運行結果:
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5045K->5045K(5120K)] 9141K->9141K(9728K), [Metaspace: 3356K->3356K(1056768K)], 0.1506820 secs] [Times: user=1.05 sys=0.00, real=0.15 secs]
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5047K->5047K(5120K)] 9143K->9143K(9728K), [Metaspace: 3356K->3356K(1056768K)], 0.1767119 secs] [Times: user=1.11 sys=0.00, real=0.18 secs]
[Full GC (Ergonomics) [PSYoungGen: 4096K->4096K(4608K)] [ParOldGen: 5048K->5048K(5120K)] 9144K->9144K(9728K), [Metaspace: 3356K->3356K(1056768K)], 0.1575503 secs] [Times: user=0.99 sys=0.00, real=0.16 secs]
[Full GC (Ergonomics) [PSYoungGen: 4096K->0K(4608K)] [ParOldGen: 5052K->658K(5120K)] 9148K->658K(9728K), [Metaspace: 3356K->3356K(1056768K)], 0.0188752 secs] [Times: user=0.09 sys=0.00, real=0.02 secs]
Heap
PSYoungGen total 4608K, used 169K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
eden space 4096K, 4% used [0x00000000ffb00000,0x00000000ffb2a498,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 5120K, used 658K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)
object space 5120K, 12% used [0x00000000ff600000,0x00000000ff6a4b48,0x00000000ffb00000)
Metaspace used 3390K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 364K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.jvm.ch05.oom.HeapOom.main(HeapOom.java:20)
原因: 本例中一直在發生fullgc中,list集合一直在塞入對象,回收內存占比越來越小,虛擬機中有個規則:垃圾回收(線程)占用超過了98%的資源,但是回收效率不足2%,就會發生了’OOM, GC overhead limit exceeded。
直接內存溢出 Direct buffer memory
分配的本地內存大小大于JVM的限制.
demo如下:
設置參數: -XX:MaxDirectMemorySize=100m
運行結果:
Exception in thread “main” java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.jvm.ch05.oom.DirectOom.main(DirectOom.java:13)
虛擬機允許的直接內存為100M.但是ByteBuffer 需要128M的空間,所以發生直接內存溢出OutOfMemoryError: Direct buffer memory。
方法區溢出java.lang.OutOfMemoryError: Metaspace
一般發生在動態語言,因為動態語言編譯后會放在方法區。
在經常動態生產大量Class的應用中,CGLIb字節碼增強,動態語言,大量JSP(JSP第一次運行需要編譯成Java類),基于OSGi的應用(同一個類,被不同的加載器加載也會設為不同的類)。如果方法區內存不夠大的話也會發生java.lang.OutOfMemoryError: Metaspace溢出。
“前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到網站?!?/p>
開通了個微信公眾號:
搜索: 怒放de每一天
后續可能不定時推送相關文章,期待和大家一起成長!!
大功告成!!
總結
以上是生活随笔為你收集整理的常见的Java内存溢出情况和实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAS操作产生的ABA问题
- 下一篇: Java开发快递物流项目(6)