性能优化案例:内存泄漏排查
监控系统显示:应用内存每天增长 200MB,第三天凌晨触发 OOM 重启。服务开始变得不稳定,用户开始投诉。
问题背景
内存趋势:
- 第 1 天:1.2GB → 1.4GB
- 第 2 天:1.4GB → 1.6GB
- 第 3 天:1.6GB → 触发 OOM
GC 日志显示:
这是典型的内存泄漏:内存持续增长,GC 无法回收。
排查步骤
第一步:导出 Heap Dump
第二步:使用 MAT 分析
打开 MAT,加载 Heap Dump。
第三步:Leak Suspects 报告
MAT 自动生成 Leak Suspects 报告:
第四步:定位泄漏点
查看 Dominator Tree:
第五步:查看引用链
查看 Path to GC Roots:
根因分析
CacheManager.java
问题是:缓存只有写入,没有清理。缓存无限增长。
修复方案
方案一:使用 WeakHashMap
方案二:添加过期机制
修复效果
排查流程总结
常见内存泄漏模式
经验总结
教训一:监控要到位
添加内存监控,及时发现内存增长趋势:
教训二:Heap Dump 是排查利器
内存问题必须看 Heap Dump:
- MAT 的 Leak Suspects 自动分析
- Dominator Tree 找保持对象
- Path to GC Roots 找引用链
教训三:修复后要验证
Heap Dump 修复前后对比:
本章小结
内存泄漏排查的标准流程:
- 监控发现:内存持续增长
- Heap Dump:导出堆转储
- MAT 分析:Leak Suspects + Dominator Tree
- 定位泄漏:GC Roots 路径
- 修复代码:添加清理机制
- 验证效果:确认修复有效
延伸思考
为什么 Heap Dump 这么大还能分析?
MAT 使用了多种优化:
- 流式处理:不需要将整个文件加载到内存
- 索引结构:快速查询对象关系
- 只保留必要数据:不保存对象内容(对于分析来说)
即使是 10GB 的 Heap Dump,MAT 也能在几分钟内完成分析。