Java应用内存性能监控需聚焦五类指标:堆内存使用率与分布、GC行为、对象晋升与存活、非堆内存与类加载、内存池与回收效率,分别通过jstat、JMX、JavaMelody等工具量化分析。

Java 应用内存性能监控的核心,是看清堆内对象生命周期、识别内存压力来源、预判 GC 风险。不靠猜,靠指标——关键就看这五类。
堆内存使用率与分布
重点关注 HeapUsed / HeapMax 比值,以及新生代(Young)、老年代(Old)、元空间(Metaspace)各自的使用率。长期高于 75% 就该警惕;若老年代使用率持续缓慢上升且不回落,大概率存在内存泄漏或对象过早晋升。新生代使用率频繁打满,说明 Eden 区偏小或短生命周期对象过多。
- 建议设置
-Xms与-Xmx相等,避免动态扩容带来的波动 - 用
jstat -gc <pid>或 JMX 的MemoryUsage.used实时查看 - 配合 JavaMelody 的堆内存趋势图,观察一天内波峰波谷是否规律
GC 行为指标
GC 不是“发生了就行”,要看它怎么发生、花多久、多频繁。核心三项:GC 次数(GCCount)、单次停顿时间(GCTime)、GC 原因(GCCause)。Young GC 每分钟超过 10 次,说明分配速率过高或 Survivor 区太小;Old GC(Full GC)每小时出现多次,必须立即排查。
- 通过
jstat -gc -h10 <pid> 2s每 2 秒刷新一次,观察 GC 频次节奏 - 关注
G1OldGC或ConcurrentMarkSweep等具体原因,区分是内存不足触发还是 CMS 失败退化 - JavaMelody 中的 “Garbage Collector” 页面可直接对比不同收集器的吞吐与延迟表现
对象晋升与存活行为
真正压垮老年代的,不是大对象,而是大量中年对象“提前退休”。晋升速率(Promotion Rate) 和 老年代活跃对象占比 是两个隐性但关键指标。如果每次 Young GC 后,进入老年代的对象大小接近 Eden 区容量,说明 Survivor 区溢出或 MaxTenuringThreshold 设置过低。
立即学习“Java免费学习笔记(深入)”;
- 用
jstat -gc <pid>中的OU(Old Used)变化量除以 Young GC 间隔,粗略估算晋升速率 - Arthas 的
vmtool --action getInstances --className java.lang.String --limit 10可辅助验证对象存活情况 - 理想状态下,老年代长期存活对象应稳定在总容量的 20%~30%,而非随请求线性增长
非堆内存与类加载状态
元空间(Metaspace)爆满会导致 OutOfMemoryError: Metaspace,常被误判为堆内存问题。需同时监控 Metaspace.used、CompressedClassSpaceSize 和 LoadedClassCount。微服务场景下,热部署、反射生成类、Groovy/SpEL 使用多,极易引发类泄漏。
- 设置
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m限制上限 - 若
LoadedClassCount持续上涨且不下降,配合jcmd <pid> VM.native_memory summary查看类元数据占用 - JavaMelody 的 “Classes” 页面可直观展示已加载类数量及趋势
内存池与回收效率
JVM 内存不是一块铁板,而是分池管理。除了整体堆,还要盯住各内存池的 usage threshold crossing 和 collection usage。比如 G1 中的 G1 Old Gen 池若频繁触发 Mixed GC,说明老年代碎片化严重;CodeCache 接近上限会禁用 JIT 编译,导致性能断崖式下跌。
- 通过 JMX 查询
MemoryPoolMBean 获取每个池的 committed/used/max - 关注
CodeCache.used是否超 80%,超限后方法将退化为解释执行 - JavaMelody 的 “Memory Pools” 页面列出所有池,支持点击下钻查看 GC 前后变化



















