记录OOM的排查过程

场景1

背景: 突然收到服务器告警短信,抓紧起来看下
记录OOM的排查过程_第1张图片

问题定位思路:
1、 看下当前的内存实例大小还能不能看了,并不能,已经挂了
2、 oom瞬间,运维脚本生成的当时dump还在不在,因为jdk版本不一致,命令失败了。
3、先重启吧,并不能影响线上功能
4、恢复后,再分析下吧
分析过程:
1、当前模块其实是task模块,都是定时任务,找到当前时间节点的定时任务
记录OOM的排查过程_第2张图片

2、找到任务,先看下是不是查询出大的对象到内存了
果然,没分页,直接查所有数据,两个定时任务相当于同时查了
百万级数据到内存,分页查询,错开定时任务时间。前人的坑啊

总结:
1、先抓紧看下,能不能留下线索,方便后面定位分析
2、线上挂了,无论发现没,抓紧重启,减少影响
3、先尝试根据时间,模块,报错,慢请求这些方面快速定位下
4、上述定位不到,有dump的情况下,还是借助mat或jprofile专业工具定位。

场景2

代码背景: 系统上传图片到其他平台,需要对图片进行剪裁,压缩,处理等操作,发生OOM

定位思路:
1、jmap 打印存活实例,看下是否有 存在问题的业务对象

jmap -histo:live 19277

发现有大量的byte[] ,char [] int[]等基础数据结构,OOM发生是在大量图片上传时产生,第一反应,是检查对应代码
记录OOM的排查过程_第3张图片
先检查流是否正常关闭,图片对象是否置为null,内容是否刷新,完善该部分逻辑后,发现还是OOM依然发生,继续往下定位
记录OOM的排查过程_第4张图片
2、arthas或者 jstat 查看GC信息

jstat -gcutil 19277 1000 5
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
16.01 0.00 88.12 73.15 94.12 90.92 136 3.739 21 2.883 6.622
16.01 0.00 90.86 73.15 94.12 90.92 136 3.739 23 2.883 6.622
0.00 16.99 96.10 73.15 94.12 90.92 137 3.751 24 2.883 6.634
97.52 0.00 6.38 73.15 94.12 90.92 138 3.786 25 2.883 6.670
97.52 0.00 60.78 73.15 94.12 90.92 138 3.786 29 2.883 6.670

也可以 arthas的 dashbord

发现fullGC频率特别高,YoungGC并不能将对象全部回收掉,会进入老年代,但是老年代GC时,垃圾也是可以回收掉的,说明并不存在泄漏无法回收的情况,怀疑只是年轻代太小了,图片大对象来不及回收进入了老年代

调大内存为1G,OOM频率变慢,但是依旧会发生

2、dump下来堆栈当时的情况,利用mat或者profile来分析

jmap -dump:live,format=b,file=dum文件名 pid
例如:jmap -dump:live,format=b,file=test5.bin pid,
忘记具体命令时,可利用jmap --help来查看

利用mat处理
第一步利用上面的命令dump下来
第二步打开文件:记录OOM的排查过程_第5张图片

首页其实有工具问题分析的,可以先看下工具的分析,detail里面有具体内容: 记录OOM的排查过程_第6张图片
我们发现,其实还是图片处理,读写操作时,占用了大量的内存,没看出代码的问题,再看下对象等信息

主要看这两个记录OOM的排查过程_第7张图片
这个类似于jmap的存活实例,但是我们可以利用工具深入分析

也可以看到GC root,是否有泄漏的地方

到这里我们发现,buffedImage对象占用内存较多,但是引用直接指向了Thread,说明是我们自己new出来的对象,也及时释放了,并没有有问题的代码
记录OOM的排查过程_第8张图片
到这里我们还是没有发现,其实我在这种情况下卡了好几天,完全不知道怎么进行下去了,没啥问题
现在再回头想一下之前获得的信息,
1、我们已经检查了,资源其实都已经及时释放了,并且通过dashbord或者jstat 看GC信息可以看出来的
2、频繁的fullGC,说明内存真的小了,最起码年轻代小了,进入老年代了
3、这种情况是否正常,百度也查到过,bufferedImage对象,在处理图片时,直接处理像素点,其实本身就会消耗大量的内存,一张图片会扩大十几倍甚至几十倍,内存本来就不够
4、通过mat查看了内存对象,没有什么特别怀疑的对象

结果:经过大佬建议,调整tomcat内存为2G,来处理业务,发现GC降下来了,在廉价的年轻代GC,就已经回收了垃圾对象,并没有fullGC

有时候查不到问题,其实真的可以想想,是不是内存真的不够呢,而不是盲目的怀疑代码处理问题

后续:
其实图片处理这种方式,个人觉得还是太耗资源了,后续还是利用GM来操作吧,这样就不依赖JVM的资源,而是利用服务器的资源来操作。具体可以看下 http://www.graphicsmagick.org/utilities.html

你可能感兴趣的:(调优)