问题背景
今天接到反馈生产环境一批量功能报错,查看生产环境发现报了OOM,遂进行排查定位排查过程
首先,第一反应查看服务启动jvm参数,

发现该服务设置了最大堆内存为1024m即1G,当时设置这个的初衷可能是想对这个核心服务设置较大的内 存,但是设置1024m真的比默认的会大吗?
了解到部署该服务的服务器是8和32G配置,网上查阅资料,得知-Xmx默认值可以达到物理内存的1/4(存 疑,未找到官方说法,不过可以确定会远远大于当前配置的1G)紧急解决方案
通过以上分析可知,由于我们之前没搞清楚-Xmx默认大小以及机器物理内存大小,设置的-Xmx=1024m反而设置小了。因为生产环境时间紧迫,先去到-Xmx -Xms两个参数,重启服务,持续观察,再未出现OOM的情况。
OOM排查
以上紧急处理方法只是治标不治本,为防止该问题以后再发生,需要搞清楚为什么会包OOM。- 日志分析

通过错误日志定位到具体代码位置,以及疑似与字符串拼接有关,下图是问题代码:

找到问题代码,发现是对一个集合进行fastjson的转json字符串操作,初步定位是fastjson的转json字符串出现的问题。
内存快照分析
首先需要在启动脚本中指定参数:-XX:+HeapDumpOnOutOfMemoryError,让发生OOM后将内存快照保留下来(具体快照文件需要生成在哪个目录命令可自行百度)

内存快照长下面这个样子:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NtKwuwn1-1643279017266)(C:\Users\18392\AppData\Roaming\Typora\typora-user-images\image-20220127180809553.png)]](https://img-blog.csdnimg.cn/ba7089ebb7094730b7065586927a1d02.png)
内存快照分析工具,目前使用过两个:1.MemoryAnalyzer (可自行百度下载)2.jvisualvm(这个是jdk自带的,已jdk1.8为例,是 %java_home%/bin/jvisualvm.exe 这个,双击打开就行):

用jvisualvm分析:

发现char[]占的内存最大,达到76%,双击看其示例中内容:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jWC2qem2-1643279017267)(C:\Users\18392\AppData\Roaming\Typora\typora-user-images\image-20220127181419926.png)]](https://img-blog.csdnimg.cn/a4b072481ff84041ada60e560f34470a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATXJfX3NpbW9u,size_20,color_FFFFFF,t_70,g_se,x_16)
发现这个示例中的内容就是报错代码 JSON.toJSONString(visitorsCountDos) visitorsCountDos集合中每个元素的参数,由此可以分析出,这些char[]大多数是JSON.toJSONString(visitorsCountDos)执行时fastjson拼接集合中对象的属性,因为这个集合数据太大了,导致fastjson序列化拼接时占用内存太多,而内存溢出。
结论
- 数据太大(尤其集合)不要使用fastjson的JSON.toJSONString()可能会造成内存溢出
- jvm参数配置前一定要搞清楚每个参数的含义再配置,否则可能南辕北辙
记一次OOM的排查定位处理(OutOfMemoryError排查)
版权声明:本文为Mr__simon原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。