说明
测试环境出现非常慢,测试说执行过工单word导出就出现这种问题
排查步骤
1.查看机器cpu和内存 正常
2.排查gc回收 发现一只在触发full gc
jstat -gc 10755
3.dump堆信息进行分析
jmap -dump:format=b,file=/Users/liqiang/Desktop/logs/heap.hprof pid
4.先通过Vm查看
根据大对象名字看不出什么问题
5.使用MAT 导入dump文件进行分析
6.前面3个都是相同的堆栈看业务代码是导出 高度嫌疑
7.点击Details当前执行线程运行引用的对象信息
可以发现freemarker.core.SimpleCharStream 为大对象类
8.可以通过右键查看当时对象的引用信息和成员变量信息
9.一般查看内存泄露都是看引用refrences
可以看出源头是template 的parser引用tokenSource ....
10.MAT我感觉不直观可以使用VM
11.跟源码发现parse在初始化后就置空了销毁了,理论上垃圾回收期会回收
12.看线程堆栈确实是在template 构造函数触发的大对象占用得不到释放
13.最后根据业务代码定位到 调用了2次fremakker渲染
14.最后怀疑是不是第一次已经填充了数据,整个结果非常大 因为含有图片。图片针对word导出是填充的图片的base64的数据
第二次根据第二次的结果再进行渲染因为太大 导致异常在template卡死
优化后发布可以正常导出了
一些误区
这个场景其实原有对象内存占用非常小,但是原有对象引用了字符串对象导致长期得不到释放