java堆用于存储对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清楚这些对象,就会在对象数量达到最大堆的容量限制后产生内存溢出异常。
下面给出例子代码体验一下java堆溢出的过程:
1.通过jvm参数(-Xms20M -Xmx20M -Xmn10M ),限制java 堆的大小
2.通过jvm参数(-verbose:gc -XX:+PrintGCDetails )打印GC的过程信息
3.通过jvm参数(-XX:+HeapDumpOnOutOfMemoryError),可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照。
- package com.jaynol.jvm.oom.sample;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * VM Args:
- * -verbose:gc -XX:+PrintGCDetails
- * -Xms20M -Xmx20M -Xmn10M -XX:+HeapDumpOnOutOfMemoryError
- * @author Johnny
- *
- */
- public class HeapOOM {
- static class OOMObject{}
- /**
- * @param args
- */
- public static void main(String[] args) {
- List<OOMObject> list = new ArrayList<OOMObject>();
- while(true){
- list.add(new OOMObject());
- }
- }
- }
[GC [DefNew: 7669K->1024K(9216K), 0.0146870 secs] 7669K->4602K(19456K), 0.0147209 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
[GC [DefNew: 9216K->1024K(9216K), 0.0200416 secs] 12794K->10520K(19456K), 0.0200646 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
[GC [DefNew: 9216K->9216K(9216K), 0.0000159 secs][Tenured: 9496K->5712K(10240K), 0.0564110 secs] 18712K->14138K(19456K), [Perm : 166K->166K(12288K)], 0.0564723 secs] [Times: user=0.06 sys=0.00, real=0.06 secs]
[Full GC [Tenured: 5712K->5712K(10240K), 0.0396698 secs] 14625K->14625K(19456K), [Perm : 166K->166K(12288K)], 0.0396968 secs] [Times: user=0.05 sys=0.00, real=0.04 secs]
[Full GC [Tenured: 5712K->5700K(10240K), 0.0441324 secs] 14625K->14612K(19456K), [Perm : 166K->166K(12288K)], 0.0441718 secs] [Times: user=0.05 sys=0.00, real=0.04 secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1340.hprof ...
Heap dump file created [29756494 bytes in 0.462 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at com.jaynol.jvm.oom.sample.HeapOOM.main(HeapOOM.java:24)
Heap
def new generation total 9216K, used 8920K [0x33210000, 0x33c10000, 0x33c10000)
eden space 8192K, 100% used [0x33210000, 0x33a10000, 0x33a10000)
from space 1024K, 71% used [0x33a10000, 0x33ac6038, 0x33b10000)
to space 1024K, 0% used [0x33b10000, 0x33b10000, 0x33c10000)
tenured generation total 10240K, used 5700K [0x33c10000, 0x34610000, 0x34610000)
the space 10240K, 55% used [0x33c10000, 0x341a10b8, 0x341a1200, 0x34610000)
compacting perm gen total 12288K, used 168K [0x34610000, 0x35210000, 0x38610000)
the space 12288K, 1% used [0x34610000, 0x3463a390, 0x3463a400, 0x35210000)
ro space 10240K, 42% used [0x38610000, 0x38a4f150, 0x38a4f200, 0x39010000)
rw space 12288K, 54% used [0x39010000, 0x3968fad8, 0x3968fc00, 0x39c10000)
从运行结果可以看出,经过JVM的3次Minor GC,再经过两次full GC后已经无法再GC了,空间已经无法再扩展了,最终导致了OutOfMemoryError