记一次FullGC的排查

现象

凌晨六点钟生产环境报警,fullgc频次突然增多,手机不断收到报警短信。登陆上服务器后一切又正常了,即触发FGC可能跟某个特定的操作或者定时任务相关。随后第二天,又突发报警FGC,这次时间是下午5点钟。

过程

根据现象应该可以排除是定时任务引起的FGC报警,因为不是周期性报警。查阅打点日志,发现这两个时间段都有一个相同的操作:用户上传了若干4M大小的Excel文件。
功能描述一下:后台批量导入先将excel上传到TFS(淘宝文件系统),服务端拿到文件的key从TFS下载,然后解析Excel,使用的是POI框架。

  • 先将该文件下载到本地,在测试环境执行同样的操作,发现FGC情况必现。
  • 打开该excel文件,发现里面只有13行数据,但是每一行都有1048576列!猜想是POI解析excel的时候,持有了1048576*13个cell
  • 再在测试环境执行同样的操作,登录测试服务器,抓取了两个DUMP文件
  • 打开MAT工具,观察内存对象的占用情况

验证


这样是第一个DUMP文件,GC开始之前,可以看到大量的ElementXobjAttrXobj对象。POI相关的对象总占用内存约5.8G,而总内存大小约为8G,必然引起FGC。

这是第二个DUMP文件,GC进行中,可以看到1中大量的对象成为了不可达对象,GC的目标就是要释放这些对象的空间。

解决方案

服务端只对最大行数进行了限定,目前限定了最大300行。但是这个用户可能是随手一贴,导致出现了我们没有预料到的情况。因为解析实在最大行校验之前进行的,所以没有起到任何效果,更何况用户也只有13行。
针对这种情况,我查了POI的API,并没有发现可以只针对指定区域(REGION)解析,加上需要立刻修复,采取的方案是将我们所有导入模版中列数最多的选出来,填满300行数据(其实不会出现全部列都有数据),得到理论最大值大概是100KB,在下载文件后检验文件大小,超过2>>17(128KB)则停止继续解析动作,抛异常提醒用户检查excel。

总结

很多时候你根本不知道用户会如何使用你提供的功能,多思考一点终归是没错的,这个例子中修复的紧急程度其实并不高,上线一年多,只发生了这一次,是极端情况,发现了就用最简单经济的方式解决它。

相关信息

FGC是怎么发生的?

FullGC触发情况

MAT是如何使用的?

MAT使用笔记

作者: wuzhaoyang(John)
出处: http://wuzhaoyang.me/
因为作者水平有限,无法保证每句话都是对的,但能保证不复制粘贴,每句话经过推敲。希望能表达自己对于技术的态度,做一名优秀的软件工程师。