1. Arthas简介与内存泄漏排查场景
第一次接触Arthas是在一个深夜的线上告警中——我们的订单服务内存占用突然飙升到90%。当时用jmap导出的堆转储文件足足有8GB,MAT分析到一半就直接OOM了。后来团队里的架构师扔给我这个阿里开源的诊断工具,我才发现原来排查JVM问题可以这么优雅。
Arthas最让我惊艳的是它的实时交互能力。不像传统工具需要停机分析,它能在应用运行时直接挂载诊断,通过命令行交互查看内存、线程、类加载等信息。特别是排查内存泄漏时,memory命令能实时观察堆内存变化,heapdump生成的文件也比jmap小很多。有次我仅用200MB的堆转储就定位到了ThreadLocal泄漏问题。
常见的内存泄漏场景主要有三种:
- 集合类持有引用:比如全局的HashMap不断添加缓存对象
- 线程池堆积任务:像我们遇到的订单处理线程池阻塞
- 未关闭的资源:数据库连接、文件流等
2. 环境准备与问题复现
2.1 模拟内存泄漏案例
先准备一个故意制造泄漏的Demo(完整代码见GitHub):
public class MemoryLeakDemo { static List<byte[]> leakList = new ArrayList<>(); // 泄漏容器 public static void main(String[] args) throws Exception { while (true) { leakList.add(new byte[1024 * 1024]); // 每秒泄漏1MB Thread.sleep(1000); } } }启动时加上内存限制参数:
java -Xms100m -Xmx100m MemoryLeakDemo2.2 Arthas快速接入
下载并启动Arthas:
wget https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar看到控制台输出目标进程时,输入对应编号即可挂载。我常用的是dashboard命令,它能实时显示:
Memory used total max usage heap 65M 256M 1024M 6.37% nonheap 45M 62M -1 72.58%3. 实时内存监控与分析
3.1 memory命令深度使用
输入memory会显示关键内存区域数据:
Memory used total max usage heap 78.3MB 100.0MB 100.0MB 78.3% nonheap 35.2MB 56.0MB -1 62.8% codeheap 'non-nmethods' 3.4MB 5.0MB 68.0%重点关注Old Gen区的增长趋势。如果持续上升不回落,很可能存在泄漏。我一般会配合-i参数定时采样:
memory -i 5000 # 每5秒刷新一次3.2 堆内存快照生成
当发现Old Gen异常时,立即用heapdump保存现场:
heapdump /tmp/demo.hprof这个命令比jmap更安全:
- 不需要指定进程ID
- 默认会进行压缩
- 支持只dump存活对象
4. 堆转储文件分析实战
4.1 MAT基础分析
用Eclipse Memory Analyzer打开dump文件,重点关注:
- Histogram:按类统计实例数
- Dominator Tree:显示对象引用链
- Leak Suspects:自动分析泄漏点
4.2 OQL查询技巧
在MAT中使用OQL定位大对象:
SELECT * FROM byte[] WHERE toString(runtimeClass).contains("MemoryLeakDemo")这个语句能快速找到我们Demo中泄漏的byte数组。
5. 进阶内存诊断技巧
5.1 结合jvm命令
查看GC详细情况:
jvm -gc输出示例:
G1 Young Generation: Eden Space: [0x00000000f0c00000,0x00000000f0c01000,0x00000000f0d00000) Survivor Space: [0x00000000f0d00000,0x00000000f0d00000,0x00000000f0e00000)5.2 监控特定类
用sc命令查看类加载信息:
sc -d *MemoryLeakDemo输出会显示类加载器、来源JAR包等关键信息。
6. 内存问题修复与验证
找到泄漏点后,常见的修复方式有:
- 修复集合引用:改用WeakHashMap
- 清理线程局部变量:及时remove() ThreadLocal
- 资源关闭:实现AutoCloseable接口
修复后可以用jmap -histo:live验证对象是否被回收。
记得有次修复一个缓存泄漏后,堆内存从4G直接降到800MB,那种成就感比写完十万行代码还爽。建议每次修复后持续监控24小时,有些泄漏是定时任务触发的。
7. 生产环境注意事项
- 安全限制:用
--target-ip限制访问IP - 性能影响:heapdump时暂停线程,避开高峰
- 权限控制:禁止普通用户执行高危命令
推荐在预发环境充分测试,我用Arthas排查过的线上问题,从没因为工具本身引发故障。