java监控jvm堆外内存需协同三种方式:1.用bufferpoolmxbean获取direct buffer用量;2.通过memorypoolmxbean查看metaspace等非堆内存;3.结合nmt、rss差值与jmx综合估算全量堆外内存。

Java 中监控 JVM 堆外内存使用总量,不能靠 Runtime 或常规堆内存 MXBean,因为堆外内存(Direct Buffer、Unsafe 分配、JIT CodeCache、Metaspace 的部分底层开销等)不归属 JVM 堆管理范畴。需结合 JVM 内置指标、系统级观测与代码层主动跟踪三种方式协同判断。
用 ManagementFactory 获取 Direct Buffer 使用量(最常用且可靠)
JVM 从 Java 8u20 开始通过 java.nio.BufferPoolMXBean 暴露直接缓冲区(DirectByteBuffer)的统计信息,这是堆外内存中用户可控、最易泄漏的部分:
- 调用
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)获取所有缓冲池实例 - 通常只有一个名为
direct的池(部分 JDK 版本还含mapped,对应内存映射文件) - 每个
BufferPoolMXBean提供:getUsed()(当前已分配字节数)、getTotalCapacity()(累计分配峰值)、getCount()(活跃缓冲区个数)
示例代码:
List<bufferpoolmxbean> pools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
for (BufferPoolMXBean pool : pools) {
if ("direct".equals(pool.getName())) {
System.out.printf("Direct Buffer Used: %d MB%n", pool.getUsed() / 1024 / 1024);
}
}</bufferpoolmxbean>
⚠️ 注意:该值仅反映 ByteBuffer.allocateDirect() 及 NIO 框架(如 Netty)使用的 Direct Buffer,不包含 Unsafe.allocateMemory()、JNI 分配或 JVM 自身元数据开销。
通过 JMX 查看 Metaspace 和 Compressed Class Space 占用
Metaspace 属于非堆但由 JVM 管理的原生内存区域,其用量可通过标准 MXBean 获取:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()返回整体非堆用量(含 Metaspace、CodeCache、Compressed Class Space) - 更细粒度:遍历
ManagementFactory.getMemoryPoolMXBeans(),筛选getType() == MemoryType.NON_HEAP且getName()含Metaspace或Compressed Class Space的池
这部分内存虽属“非堆”,但属于 JVM 显式管理的堆外内存,是总堆外用量的重要组成。
观察进程 RSS 内存减去 JVM 堆/非堆理论上限
当需要估算**全部堆外内存总量**(含 JNI、第三方 native 库、JVM 内部结构等),可借助操作系统视角做差值估算:
- 用
ps -o pid,rss,vsz -p <pid></pid>或jcmd <pid> VM.native_memory summary</pid>(需开启-XX:NativeMemoryTracking=summary)获取进程实际物理内存占用(RSS) - 计算 JVM 理论最大内存上限:
maxMemory() + nonHeapMemoryUsage.getMax()(注意:nonHeap max 常为 -1,此时取各 non-heap pool 的 max 之和) - 差值 ≈ 其他堆外开销(native code、线程栈、glibc malloc 碎片、未追踪 native 分配等)
⚠️ 此法为估算,受内存映射、共享库、内核缓存等影响,适合趋势观察而非精确值。
启用 Native Memory Tracking(NMT)获取详细原生内存分布
这是 JVM 官方提供的最权威堆外内存分析能力,需启动时开启:
- 添加 JVM 参数:
-XX:NativeMemoryTracking=detail(或summary) - 运行中执行:
jcmd <pid> VM.native_memory summary</pid>查看汇总,或details查看各子系统(Java Heap、Class、Thread、Internal、GC、Compiler、Runtime 等)用量 - 支持 diff 比较:
jcmd <pid> VM.native_memory summary.diff</pid>观察内存增长来源
NMT 是定位堆外内存异常上涨根源的首选手段,但有约 5–10% 性能开销,生产环境建议按需开启并及时关闭。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










