Java OOM问题排查


1.问题现象

tomcat web页面无法访问,日志报出如下错误,

问题出现频率 1晚上1次。

有时候会打印出oom的代码位置,有时候不会打印,不会打印则按照如下流程排查

2.问题排查过程

排查OOM主要是要获取内存的快照文件,但此时jvm已经僵死,无法通过jmap打印内存dump文件。     所以修改tomcat启动脚本增加export JAVA_OPTS 这行增加 如下内容

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/tomcat-heap-dump.hprof  

这里表示,当出现oom异常时会自动把当时的内存快照文件打印到/data/tomcat-heap-dump.hprof

2.1修改tomcat启动脚本

// 1.进入docker     
docker exec -it tomcat /bin/bash

//2.打开catalina.sh 
vi /data/apache-tomcat-9.0.71/bin/catalina.sh 

//3.找到export JAVA_OPTS=这行,增加如下内容,保证下次出险oom时,自动打印对快照。
//-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/tomcat-heap-dump.hprof

//4.重启tomcat
docker restart tomcat

2.2分析tomcat-heap-dump.hprof文件

在下次出现oom时,会自动dump出内存快照,使用jprofile打开该快照文件一共35G,打开第一次需要花费的时间比较久。

打开之后如下图所示hashmap的Node有1.98亿

点击 biggest object,看到mybatis返回的list占16G

如果点击biggest object没有大对象占用,那么可以选择group by class,分组可以知道某个对象虽然很小,但是可能某一类却很多。这样也能分析出内存异常占用问题,下图就是这种情况。

右键选择 Use selectd objects

选择如下点击ok

2.3 查看堆栈信息

接2.2最后一步之后,

点击show more,可以看到传入的堆栈信息,发现是我们项目代码造成内存占用这么大

3.最后分析具体代码

经过分析是由于该导出定时任务,分页参数失效做了全表查询,该表在mysql中有5个G。经过导入到内存中可能存储容量就翻倍了,因为堆内存中有其他对象信息加起来可能会比原先的数据量大很多。而且在那部分代码中做了两次全表查询,也就是将这5g数据导入到内存中导入了两次,随后老年代被沾满oom溢出。

该定时一天执行一次,所以一天一次OOM

4.总结

0.看日志,如果日志中打印了代码位置则直接分析相对应的代码,如果分析不出或者没打印则进行如下流程

1.拿到dump文件

2.用jprofile分析

3.找到大对象入口

4.分析具体功能具体代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值