DirectByteBuffer易泄漏因堆外内存由OS分配、Cleaner异步回收且存在延迟;需用NMT定位,配合-XX:MaxDirectMemorySize限流、缓冲池复用及主动clean()防护。

DirectByteBuffer 是 Java 中最常用、也最容易被误用的堆外内存载体。它不占用堆内存,但实际申请的物理内存由操作系统直接提供,且不受 GC 主动管理——分配靠 Unsafe.allocateMemory,回收靠 Cleaner 异步触发,中间存在明显的时间差和不确定性。而 Native Memory Tracking(NMT)正是定位这类“看不见的内存”问题的关键工具。
DirectByteBuffer 的内存分配流程
调用 ByteBuffer.allocateDirect(cap) 时,并非简单返回一个缓冲区对象,而是触发一整套底层操作:
- 先通过
VM.isDirectMemoryPageAligned()判断是否需按页对齐;若开启,则实际分配大小 = 请求容量 + 一页大小(如 4KB),确保地址对齐; - 调用
Bits.reserveMemory(size, cap)更新 JVM 内部的堆外内存总用量统计(用于配合-XX:MaxDirectMemorySize限流); - 真正向 OS 申请内存:
unsafe.allocateMemory(size),返回基地址base; - 若需页对齐且
base不在页边界,则调整address = base + ps - (base & (ps-1)),使后续访问更高效; - 最后绑定一个
Cleaner,其关联的Deallocator任务持有该base和实际容量,等待对象被 GC 后异步执行unsafe.freeMemory。
为什么堆外内存容易泄漏
根本原因在于“壳小内存大”与“回收异步”两个特性叠加:
- DirectByteBuffer 对象本身只占几十字节堆空间,很难触发 GC,尤其在长生命周期对象(如静态缓存、连接池成员)中长期持有引用;
- Cleaner 的清理依赖 ReferenceHandler 线程轮询虚引用队列,而该线程优先级低、调度不及时,可能延迟数秒甚至更久;
- 如果应用频繁创建 DirectByteBuffer 且未显式调用
cleaner.clean()或未及时断开强引用,就会造成堆外内存持续累积; - 一旦突破
-XX:MaxDirectMemorySize(默认等于-Xmx),会抛出OutOfMemoryError: Direct buffer memory,但此时 OS 层内存已大量占用,可能早被 OOM Killer 杀掉进程。
NMT 如何定位 DirectByteBuffer 泄漏
NMT 不直接显示每个 DirectByteBuffer 实例,但它能反映“Internal”或“Other”模块下异常增长的本地内存,再结合 detail 模式精准归因:
- 启动时加参数:
-XX:NativeMemoryTracking=detail -XX:MaxDirectMemorySize=512m; - 运行一段时间后,用
jcmd <pid> VM.native_memory summary查看总体分布,重点关注Internal或Other类别是否持续上升; - 若怀疑 DirectByteBuffer,切换到 detail 模式并执行:
jcmd <pid> VM.native_memory detail.diff,对比两次快照,观察malloc调用栈中是否大量出现DirectByteBuffer.<init>或Bits.reserveMemory; - 还可配合
jmap -histo:live <pid>查看堆内 DirectByteBuffer 实例数,若数量稳定但 NMT 中 native 内存持续涨,说明 Cleaner 滞后或未触发,需检查引用链。
实用防护与调优建议
不能只靠 Cleaner 被动回收,必须主动干预:
- 限制总量:显式设置
-XX:MaxDirectMemorySize=512m,避免失控增长; - 复用优先:使用 Netty 的
PooledByteBufAllocator或自建 DirectBuffer 池,减少频繁分配; - 及时释放:对短期使用的 buffer,在业务逻辑结束时手动调用
((DirectBuffer) buffer).cleaner().clean()(注意 NPE 风险,需判空); - 监控联动:将 NMT 报告接入 Prometheus(通过 JMX 或 jcmd 定时采集),设置
Internal内存增长率告警; - 避免滥用:非高性能 IO 场景(如普通 JSON 解析、小文件读写)无需 DirectBuffer,HeapByteBuffer 更安全可控。

















