Java 内存泄漏排查实战:从 MAT 到 jmap——堆外内存暴增的元凶
引言 "凌晨 2 点网关告警内存 85%,3 点 92%,4 点容器被 OOMKilled,重启后一切正常,然后 6 小时后再来一遍。" 值班的同事第一反应是堆内存泄漏,jmap、jstat、堆 dump 全做了,发现 Xmx 2G 的堆只用了 800M,Young GC 规律、Old 区平稳,MAT 里 Dominator Tree 翻了三遍没有任何大对象——但容器 RSS 实实在在涨到了 3.7G(limit 4G)。 堆没涨,进程内存涨了——这就是堆外内存泄漏的典型特征。 它比堆内泄漏阴险得多:jmap 看不见、堆 dump 里找不到、OOM 时连 hprof 都不会生成(因为是内核 OOM Killer 直接杀的进程),监控图上只有一条让你绝望的平滑上涨曲线。 这篇文章按那次事故的真实排查路径,走完六个台阶:jmap 看堆 → RSS 对不上账 → NMT 给本地内存分类 → MAT 从 DirectByteBuffer 小对象顺藤摸瓜 → Netty LEAK 检测打出 Created at 堆栈 → jemalloc 做最终归因。元凶是一个 WebSocket 推送 Han....