连载中 13/20

MAT 实战:从堆转储找出泄漏元凶

2026-09-17 · 5 阅读 · 0 评论 · 0 赞

浅堆与深堆:不只是"占多大"

MAT 里有两种"大小":浅堆(Shallow Heap)是对象自身占用的内存——一个 ArrayList 的浅堆只有几十字节(对象头 + 内部数组引用 + size 字段),并不算它装着的元素;深堆(Retained Heap)则是"这个对象被回收后能释放多少内存"——它的全部独占对象,包括内部数组和能跟着它一起死的对象。排查泄漏看深堆,理解对象本身开销看浅堆。

三步排查法

// 步骤一:看 Leak Suspects 报告(MAT 自动分析)
//   打开 hprof → MAT 自动跑一轮,列出嫌疑对象
//   常见结论:某 HashMap 占了 800M / 总堆 1G —— 直接点名
//
// 步骤二:Dominator Tree(支配树)
//   按深堆排序,最上面就是"拴住最多内存"的根
//   树状展开:父节点回收,子节点全部跟着死——谁是"真凶"一眼看出
//
// 步骤三:Path to GC Roots(强引用链)
//   选中对象 → List Objects → with incoming references →
//   选 "Path To GC Roots" → exclude weak/soft references
//   看到的引用链就是"谁拴住了它不让回收"

一个真实案例:ThreadLocal 造成的泄漏

某服务每隔几天 OOM 一次,堆转储里 70% 内存是 com.xxx.UserContext 的实例——一堆 UserContext 没被回收。Path to GC Roots 顺着强引用链摸上去:UserContext → ThreadLocalMap.Entry → Thread → 线程池里的 Worker。真凶是业务代码漏了 ThreadLocal.remove()——线程池的线程长生不老,ThreadLocalMap 里 key 虽是弱引用,value 却是强引用,每跑一个用户就攒一条 stale entry。

SQL 结果集泄漏:另一类高发

堆转储里 PreparedStatement$1、ResultSetImpl 一堆——这是 JDBC 资源没关。MySQL Connector/J 的 ResultSet 内部持有查询结果 byte[],不主动 close 就一直挂在连接对象上,连接还回池子也不会释放。MyBatis/正常 ORM 几乎不会出这事,但手写 JDBC、用 ResultSet 做缓存的场景,这种泄漏常见。MAT 里这类对象的引用链往往指向 Connection → Pool,是排查泄漏的高频路径。

实践要点

第一,dump 时机决定排查成败:最好在 OOM 前夕或内存刚涨起来时 dump,事后重启再 dump 可能问题已自愈看不到现场。配 HeapDumpBeforeFullGC 让 Full GC 前自动 dump 是最省心的。第二,转储文件别在生产分析:动辄几个 G,拷到本地用 MAT 分析更安全。第三,排除弱软引用看强引用链:默认 Path to GC Roots 包含所有引用,过滤后才能看真凶。下一篇把各种 OOM 的"出生地"做个地图。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#MAT#堆转储分析#浅堆深堆#Dominator Tree#内存泄漏排查

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞