@[TOC]JAVA内存溢出分析
在线上运行过程中,突然出现反复宕机问题分析处理过程
- 观察程序运行监控历史曲线,发现Old Gen曲线一直居高不下,并且cpu是用率飙升。分析得出结论:应该是内存溢出导致java虚拟机频繁进行GC,从而导致cpu升高。
- 启动脚本中加入-XX:+HeapDumpOnOutOfMemoryError参数,在内存溢出时会产生一个hprof后缀的DUMP文件。
- 使用IBM HeapAnalyzer加载DUMP文件进行分析,发现是一个SfcData创建了几万个对象导致,但是没法定位具体调用位置。
- 为进一步确认具体位置,将jstack编写成脚本,在程序出现异常时运行。
下面展示一些内联代码片
。
#######################pid关键字为biz的java进程中cpu>0的线程的堆栈######
pid=`ps -ef|grep biz.jar|grep -v 'grep'|awk '{print $2}'`
sfile="/opt/java.$pid.trace"
tfile="/opt/java.$pid.trace.tmp"
rm -f $sfile $tfile
echo "pid $pid"
jstack $pid > $tfile
ps -mp $pid -o THREAD,tid,time|awk '{if ($2>0 && $8 != "-") print $8,$2}'|while read line;
do
nid=$(echo "$line"|awk '{printf("0x%x",$1)}')
cpu=$(echo "$line"|awk '{print $2}')
echo "nid: $nid, cpu: $cpu %">>$sfile
lines=`grep $nid -A 100 $tfile |grep -n '^$'|head -1|awk -F':' '{print $1}'`
((lines=$lines-1))
if [ "$lines" = "-1" ];
then
grep $nid -A 100 $tfile >>$sfile
echo '' >>$sfile
else
grep $nid -A $lines $tfile >>$sfile
fi
done
rm -f $tfile
echo "read msg in $sfile"
########### end ############
- 运行脚本,输出.trace文件,通过文件分析发现addSfcData方法占用cpu相对较高,定位程序位置,最终发现原因是程序中使用Mybatis-plus的selectOne方法,对象传参的时候关键栏位为空值,导致该栏位不作为查询条件加载了过多数据导致