工作中遇到了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(); } }