工作中遇到了OOM问题需要排查,在此做一下分享,也做一下笔记
这里模拟了工作中的OOM场景,实际代码就不拿出来了,以下是我自己写的代码
定义一个无界队列,频繁往里面加入元素,代码如下,经测试,这是会产生OOM的
/**
* @author mengfh
*
* @version 2020-7-3上午9:15:52
*
* @description OOM排查与优化
*/
public class OptimizeOOM {
public static void main(String[] args) {
testQueue();
}
private static void testQueue() {
Queue<ArrayList<TestVO>> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < 10000; i++) {
ArrayList<TestVO> list = new ArrayList<>();
for (int j = 0; j < 1000; j++) {
list.add(new TestVO());
}
queue.add(list);
}
}
}
启动debug,让线程挂起,然后找到jdk/bin目录下的jconsole.exe,可以看到我们写的程序正在运行
jconsole.exe里面有很多VM相关的东西,对于我们分析和学习还是有帮助的,具体如下,信息数量比较大
既然要OOM,那我们就分析为什么OOM,这里配置一下VM参数,生成dump文件和文件地址
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/jad/heapdump.hprof
要注意的是dump文件是比较大的,我本地随便跑一下就接近1G ,而我的最大堆内存是768M
拿到了dump文件,那么就可以去分析dump文件哪里出问题了
可以通过jdk自带的jhat来分析,也可以通过相关MAT来分析,如下是Eclipse Memory Analyzer 工具
使用的话需要一定的基础,LZ一年工作经验,勉强能行,现在在逐步加强,具体使用可以去MAT官网
另外,dump文件分析可以参考这篇文章https://blog.csdn.net/sheldon178/article/details/79543671
除了jhat,jconsole和MAT以外,还有很多JDK自带的性能监控工具如:jps,jstack,jmap,jstat等等
它们都在jdk/bin目录下,可以通过cmd运行
以下是理想的解决方案,思想是把无界队列变成有界队列,然后控制生产者生产的速度和消费者线程消费的速度
OOM的产生原因很多,优化方案也很多,工作上的优化方案就不拿出来了,保密性高,怕出事
路漫漫其修远兮,吾将上下而求索
private static void testQueue() {
Queue<ArrayList<TestVO>> queue = new LinkedBlockingQueue<>(100);
for (int i = 0; i < 10000; i++) {
ArrayList<TestVO> list = new ArrayList<>();
for (int j = 0; j < 1000; j++) {
list.add(new TestVO());
}
queue.add(list);
//业务处理
//......
//这里假装是消费者线程在消费,当然还有很多方式,这是最简单的一种
queue.remove();
}
}