You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

K8s容器中Java进程内存使用量与jcmd统计值差异排查

K8s Pod中Java 17容器内存差异排查方案

先统一单位明确差值:

  • /sys/fs/cgroup/memory/memory.usage_in_bytes:1597472768字节 ≈ 1523MB
  • jcmd VM.native_memory summary已提交内存:857660KB ≈ 837MB
    两者差值约686MB,排查方向如下:

1. 深挖NMT未统计的内存细节

默认summary模式的NMT输出不够详尽,切换到detail模式查看未归类内存:

jcmd <pid> VM.native_memory detail

重点关注Unknown分类,这部分是NMT无法追踪的内存分配——Netty若通过Unsafe.allocateMemory()而非ByteBuffer.allocateDirect()分配直接内存,会被归入此类。

2. 排查Pod内非Java进程的内存占用

Cgroup统计的是整个Pod内所有进程的内存总和,而非仅Java进程。执行以下命令确认Pod内进程:

ps aux

对每个非Java进程用pmap -x <pid>查看内存占用,排除sidecar容器、日志采集进程、init进程等的内存消耗。

3. 扣除页缓存的影响

memory.usage_in_bytes包含文件页缓存,而NMT仅统计JVM进程自身内存。查看页缓存大小:

cat /sys/fs/cgroup/memory/memory.stat | grep cache

将memory.usage_in_bytes减去该缓存值后,再与JVM内存对比,差值会明显缩小。

4. 直接查看Netty的内存池状态

Redisson依赖的Netty直接内存可能未被NMT捕获,可通过两种方式验证:

  • 开启Netty内存泄漏检测:启动JVM时添加参数-Dio.netty.leakDetection.level=advanced,日志中会输出未释放的缓冲区信息。
  • 通过JMX获取Netty内存池指标:查找io.netty.buffer.PooledByteBufAllocator相关MBean,查看usedDirectMemory等字段的实际值。

此外,用pmap -x <pid>查看Java进程的内存映射,匿名映射(anon)的大区块大概率是Netty的直接内存池。

5. 验证JVM常驻内存与Cgroup RSS的匹配度

memory.usage_in_bytes包含swap和缓存,而rss(常驻内存)更贴近进程实际物理内存占用:

  • 查看Cgroup的RSS值:
cat /sys/fs/cgroup/memory/memory.stat | grep rss
  • 查看JVM的常驻内存:
jcmd <pid> VM.info | grep "Resident Set Size"

两者数值应更接近,若仍有较大差值,需排查JVM未统计的内存分配(如JNI调用的第三方库内存)。

6. 排查堆外内存泄漏风险

检查Redisson连接池配置是否合理,若连接未及时释放,会导致Netty缓冲区堆积。同时添加JVM参数开启退出时的NMT统计:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

进程退出时会输出完整的内存统计,帮助定位泄漏点。

内容的提问来源于stack exchange,提问作者Niranjan R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:47:20