常见OOM情况分析
概述
在java开发当中,由于程序员不需要手动管理内存,虚拟机有自己的GC机制来帮助管理。但是在开发中难免会出现OOM的情况。如果不了解OOM的常见原因,就会感觉无从下手,不知道怎么分析。笔者下面介绍几种常见的OOM以及可能的原因。根据不同区域OOM的特点,按区域划分
一、堆内存溢出
由于在程序执行中,堆内存的使用十分频繁,堆上实例朝生夕死,有时GC不当也会出现OOM,.在这里,我们只分析堆中对象过多,难以为对象分配内存的情况。
我们先写一段不停在堆上初始化对象的代码,再用一个list装起来,让GCRoot一直可达这些new出来的对象,不让他们被GC。
public class HeapOOM {
public static void main(String[] args) {
ArrayList<HeapOOM> list = new ArrayList();
//通过不停创建对象来使得堆内存溢出
while (true){
//加入list,防止GC
list.add(new HeapOOM());
}
}
}
其中VM args :-Xms20M(最小堆内存) -Xmx20m(最大堆内存,设置和最小的一样,防止扩展)
-XX:+HeapDumpOnOutOfMemoryError(将OOM时的Dump文件输出,未设置路径则在当前工程根目录)
运行结果:
可以看到抛出了堆内存不足的OOM异常,也可看到生成的dump文件名称
我们可以通过工具分析下dump文件,验证下我们的想法,这里笔者用jdk自带的分析程序,jhat
我们在命令行输入 jhat [dump文件名],如下图:
可以看到开了个服务在7000端口,我们访问下
点击(Show instance counts for all classes (excluding platform))按钮,我们就可以看到在OOM那一刻存活的自定义对象实例了
可以看到有810326个实例,验证了我们之前对象实例过多,分配内存失败OOM的想法。在我们开发过程中可以用这种方法来观察是否是像我们的例子一样的内存泄露的情况,也有可能是内存溢出,此时我们就要根据实际的情况调整VM参数了。但是这种方法有个局限性,在大型企业开发中,往