记录一次由于大批量Excel导出导致的内存溢出事故。
发现和处理过程
- 下午17:30左右运维反馈系统内存溢出
- 联系运维重启服务器恢复正常
- 运维将112服务器的-XX:PermSize=128M -XX:MaxPermSize=256M调整为-XX:PermSize=256M -XX:MaxPermSize=512M;
事故原因分析
根据dump文件发现17:35分左右系统产生大量的HSSFCell对象,初步判断是由于导出或者导入操作引起内存溢出
搜索日志发现下午17:35分左右有人在操作大批量数据导出,大概30w条
- 定位到对应代码,发现使用HSSFCell对象进行导出操作,网上搜索发现HSSFWorkbook类是将所有生成的单元格都读入到内存,所以会new所有的HSSFCell对象,导致内存溢出
问题解决
更换SXSSFWorkbook类进行Excel导出操作,该类在只在内存中保存特定行数,其余的行被写入到硬盘上。比如设置在内存中保留100行数据,当处理101行时,第1行的数据会写入到硬盘,这样在内存中SXSSFCell对象数量是 100乘以每一行的单元格数,所以java内存消耗微乎其微。
改动后代码: