记一次OOM堆栈信息泄漏分析过程

1、用户反映生产订单下不来,马上打开服务器查看gc日志(前提是已经先排除了业务逻辑问题)
tomcat配置:
JAVA_OPTS=”$JAVA_OPTS -server -Xms4096m -Xmx4096m -Xss1024k -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+PrintGCDetails -Xloggc:/usr/local/gc.log -XX:+PrintGCTimeStamps”
查看gc日志:
tail -f gc.log
记一次OOM堆栈信息泄漏分析过程
发现gc日志一直在作fullGc,频率在1分钟内,GC时间长达9秒,而且fullGC并没有释放出内存,因此断定服务器出问题了,查看了CPU,内存的使用率,
top -H -p pid
也发现CPU高达300%,平常是60%
为了恢复生产,此时服务器必须马上重启,但是为了查找出原因,先把堆栈信息打出来才能方便后续查找原因,保护现场很重要:
第一步:栈信息
jstack pid > jst.txt
第二步:堆信息
jmap -dump:format=b,file=jdump.bin pid
-dump: 生成Java堆转储快照
-heap:显示Java堆详细信息
-histo:显示堆中对象统计信息
然后恢复生产环境,重启,因为以前也是发生过一次这种情况,说明导致服务器挂掉的原因发生概率较小,是偶然性因素

2、分析堆栈信息:Memory Analyzer tools:AMT
分析工具采用AMT,可以在Eclipse安装也可以独立安装,打开工具,默认生成Leak Suspect report,内存泄漏报告
记一次OOM堆栈信息泄漏分析过程
首先:overview,看到的是内存占用较大的对象

然后查看是由哪个线程产生的对象
记一次OOM堆栈信息泄漏分析过程
点击 See stacktrace,可以看见栈信息
记一次OOM堆栈信息泄漏分析过程
此时可以看到自己写的代码部分
最后点击details,查看这个GC不掉的内存对象是谁?
记一次OOM堆栈信息泄漏分析过程
我们找到了线程,找到了内存对象,看来这个问题比较简单的被我们找到了问题症结点

3、回过去查找代码,此时我们至少能将问题锁定在某个具体的方法上,再去查找服务器生产业务日志,终于找到,原来是一个循环代码中,跳出条件有个隐蔽的边界条件,会导致死循环,生产服务器的日志也是一直在死循环,代码也能解释
OK,完成