一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

JVM 内存监控中如何辨识内存增长趋势

时间:2026-07-12 09:29:46 编辑:袖梨 来源:一聚教程网

内存泄漏判定关键在于观察老年代使用率(OU)的回收基线是否逐次抬高、FGC频次增加但OU降幅微小,结合堆内/堆外分路径验证及“楼梯式”增长特征,排除缓存预热、大页预留等干扰。

识别内存增长趋势不是看某一次数值高低,而是观察变化节奏和回收效果。关键不在“用了多少”,而在“用完能不能收回来”。

盯住老年代使用率(OU)的回收基线

jstat -gcutil <pid> 2s 持续观察,重点关注 OU(Old Generation Usage):

  • 每次 Full GC 后,OU 是否回落到相近水平?如果回落点逐次抬高(比如上次回落到 45%,这次落到 52%,再下次 58%),说明有对象持续堆积未释放
  • 对比 FGC 频次和 OU 下降幅度:FGC 越来越频繁,但 OU 每次只降 1–2%,基本可判定泄漏
  • 避免误判:刚启动或缓存预热阶段 OU 上升是正常的,需等待业务稳定后再观察连续 3–5 次 Full GC 行为

区分堆内与堆外增长路径

堆内(Heap)和堆外(Off-Heap)增长表现不同,需分开验证:

  • 堆内:通过 jstatmemory(Arthas)看 Eden、Old、Metaspace 等分区趋势;若 Old 区单边上涨,而 Metaspace 平稳,大概率是业务对象泄漏
  • 堆外:启用 -XX:NativeMemoryTracking=detail,用 jcmd <pid> VM.native_memory summary.diff 对比两次快照,重点看 InternalDirect memoryThread 三块是否异常膨胀
  • 容器环境额外看 RSS:用 ps -o pid,rss,comm -p <pid>cat /sys/fs/cgroup/memory/memory.usage_in_bytes,若 RSS 持续涨而 JVM 堆没涨,基本锁定堆外问题

抓取时间维度上的“楼梯式”特征

真正的泄漏在图表上呈现典型阶梯状,而非平滑曲线上升:

  • 每轮批量任务或高峰请求后,内存跳升一级,GC 后不回落或仅小幅回落,形成“一级台阶”
  • 用 Prometheus + Grafana 绘制 jvm_memory_used_bytes{area="heap"} 曲线,开启自动标注 GC 事件(通过 GC 日志打点),能清晰看到每次 GC 后的残余增量
  • 单次 heapdump 无法反映趋势,必须配合至少两个时间点的 class_histogram(jcmd <pid> VM.class_histogram)对比:看同一类对象数量是否翻倍或持续递增

排除干扰项,确认是增长而非占用

很多“增长”其实是合理占用,不是泄漏:

  • 检查是否启用了大页(HugePages)或 ZGC/Shenandoah 等低停顿 GC:它们会提前预留内存,导致 RSS 高但实际未泄漏
  • 确认是否有定时任务加载全量数据进本地缓存——这类行为会造成一次性跃升,之后稳定,不属于泄漏
  • 观察线程数是否同步上升:用 ps -T -p <pid> | wc -l,线程暴涨常伴随栈内存增长,易被误认为堆泄漏

热门栏目