记录一次生产环境OOM

生产环境突然频繁挂掉,查看日志报错OOM

光看日志没法确定原因,于是想把内存dump下来分析

首先来看看tomcat的启动脚本startup.sh,在tomcat的bin目录下(这里的版本是tomcat8.5)

启动过程中会去执行catalina.sh,以下是catalina.sh的部分内容

如果setenv.sh脚本存在的话,启动tomcat就会去执行这个脚本,这里很适合添加自定义的参数

vim setenv.sh 创建这个文件

写入:JAVA_OPTS="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Xmx6144m -Xms6144m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/www/server/tomcat/oom_dump"

esc-->:-->wq

-Dfile.encoding:指定文件内容编码格式

-Dsun.jnu.encoding:指定文件名的编码格式

-Xmx6144m:设置JVM可用最大内存为6114M

-Xms6144m:设置JVM初始内存大小为6114M

ps:这个服务器的内存为8G,分配了6G给JVM,接近极限了。

-XX:+HeapDumpOnOutOfMemoryError :在发生OOM的时候保存快照

-XX:HeapDumpPath=/www/server/tomcat/oom_dump":快照保存地址“/www/server/tomcat/oom_dump”

ps:这里一定要确认tomcat是否有权限对该文件夹进行修改,比如我这里是用www用户启动的tomcat,我用root用户登录服务器创建了/www/server/tomcat/oom_dump文件夹,默认权限是需要root权限才能访问的,setenv.sh文件也一样要注意权限问题。

命令groups [用户名] 可以查询用户所属的组,直接输入groups是查询当前登录用户的组

修改文件夹所属的组和用户,使用命令:

chown 用户名:组名 文件夹名/文件名

chown  www:www  /www/server/tomcat/oom_dump

chown  www:www  /www/server/tomcat/bin/setenv.sh

用户名没有冲突的话也可以直接使用chown  www  /www/server/tomcat/oom_dump

果不其然再次OOM。。T_T

找到/www/server/tomcat/oom_dump/java_pid12907.hprof

下载下来,然后推荐使用eclipse的MemoryAnalyzer(MAT)来分析,简单好用

打开eclipse-->help-->Eclipse Marketplace,搜索MemoryAnalyzer-->Install

MAT教程:https://www.cnblogs.com/UncleYong/p/7743294.html#MySignature

ps:依据快照文件大小可能需要调整eclipse的配置

打开eclipse安装目录-->找到eclipse.ini-->编辑,将-Xmx调大,我的快照文件是1.5G,我这里调大至-Xmx4096m,eclipse的JVM内存小于快照文件大小会导致打不开。

打开MAT面板

 

 

 Open Heap Dump -->选择快照文件会得到如下视图:

 

1.Histogram可以列出内存中的对象,对象的个数以及大小。

2. Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
3.Top consumers通过图形列出最大的object。
4.Leak Suspects通过MA自动分析泄漏的原因。

点击Dominator Tree

 这里我点开最大占用的对象

 发现是嵌套ArrayList,里面全是字符串,占用了将近700M(原本服务器设置的最大堆内存为2G)

最终找到了引发OOM的类,查找到了原因,业务是加载oss上的文件,读取文件内容存入List再转成json返回给前端,但是该文件太大了。

修改接口为只返回文件路径给前端,点击查看才尝试加载文件,如果大小超过2M则提示不支持预览,请下载后查看。

另外Leak Suspects-->Details-->See stacktrace也能定位到问题发生的位置。

 本文有不当之处还请各位看官不吝赐教,感谢查看。

猜你喜欢

转载自www.cnblogs.com/zou-rong/p/11952825.html
今日推荐