一,什么是OOM,原因有哪些
OOM也叫内存溢出,导致OutOfMemoryError异常的常见原因有以下几种:
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
- 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
- 代码中存在死循环或循环产生过多重复的对象实体;
- 使用的第三方软件中的BUG;
- 启动参数内存值设定的过小;
二,通过一个案例定位排查
首先,看一下产生OOM的代码,它的语义是无限往集合中添加元素
import java.util.*; public class OomTest{ public static void main(String [] args){ List<String> list = new ArrayList<String>(); while(true){ list.add(new String("test")); } } }
首先介绍下用到的日志的概念以及工具:
Heap Dump是什么?
Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。Heap Dump是有着多种类型的。不过总体上heap dump在触发快照的时候都保存了java对象和类的信息。通常在写heap dump文件前会触发一次FullGC,所以heap dump文件中保存的是FullGC后留下的对象信息。
IBM heapAnalyzer:
这是分析Heap Dump的工具,可以通过此连接进行下载https://download.csdn.net/download/cts314/8226597
为了复现这个问题,我们需要通过命令:-Xmx10m 去调低内存大小为10M 。为了排查问题,我们需要通过命令生成heap dump文件( -XX:+HeapDumpOnOutOfMemoryError)
如我们所料,果然出现了OOM。标红的以 .hprof结尾的文件,即是heap dump,他会生成在classpath目录下。
我们找到这个文件,然后用之前下载好的IBM heapAnalyzer打开,
然后我们点击左上角的Analysis 选择Objects List,可以看到如下界面:
我们可以看到前两行的totalSize非常大,通过分析,我们可以得出有很多的对象存储在了list当中。
或者我们也可以点击左上角的Analysis 选择Tree View,可以看到如下界面:
想必看到这里大家也就一目了然了。