一、溢出条件
Java堆用于存储对象实例,只要不断创建对象,并且保证GC Roots到对象之间有可达路径来保证垃圾回收机制无法回收这些空间,那么随着对象数量的增加,总容量触及到最大堆内存限制后,会触发OutOfMemoryError异常。
二、VM参数
-Xms20m //Java堆初始大小为20MB
-Xmx20m //Java堆最大大小为20MB,设置与初始值相同可避免内存扩展
-XX:+HeapDumpOnOutOfMemoryError //在堆内存溢出时进行堆内存转储,便于后续分析
三、演示代码
package OOM;
import java.util.ArrayList;
import java.util.List;
/**
* VM Options: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
*/
public class HeapOOM {
static class OOMObject{
}
public static void main(String[] args) {
List<OOMObject> list=new ArrayList<OOMObject>();
while (true){
list.add(new OOMObject());
}
}
}
四、运行结果
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid13548.hprof ...
Heap dump file created [28281635 bytes in 0.175 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at OOM.HeapOOM.main(HeapOOM.java:17)
五、jvisualvm.exe
类名 | 实例数(%) | 实例数 | 大小 |
---|---|---|---|
OOM.HeapOOM$OOMObject | 99.01610258340277 | 810,326 (99%) | 12,965,216 (64.1%) |
通过jvisualvm可以快速定位问题所在
- 当出现内存泄露时,通过工具检查对象到GC Roots的引用链,找到泄露对象是通过怎样的引用路径、与哪些GC Roots相关联,才导致垃圾收集器无法回收他们。(根据对象的类型以及对象到GC Roots的引用链信息,一般可以准确定位到对象创建的位置)
- 当出现内存溢出时,适当调节对象的堆参数-Xms、-Xmx,并检查是否存在某些可以优化的对象(生命周期过长的、存储结构不合理的)
- 当dump出的堆转储文件特别小且发生OOM异常时,检查直接内存(Direct Memory)使用是否合理