gc日志是判断内存碎片化最直接依据,关键看三类信号:晋升失败(promotion failed)、老年代回收无效(r值<1%)、大对象分配受阻(humongous allocation失败),配合gceasy中fragmentation%>25%可确诊。

GC日志是判断内存碎片化是否严重最直接、最可靠的依据,不需要等OOM发生,也不依赖堆dump。关键在于识别三类日志信号:晋升失败、老年代回收无效、大对象分配受阻。
看“Promotion Failed”是否高频出现
这不是普通警告,而是碎片化的临床确诊标志。在GC日志中搜索 Promotion Failed,一旦出现,说明Survivor区已满,且老年代没有足够连续空间容纳晋升对象——即使老年代总使用率只有70%,也可能因碎片而无法分配。
- 若该字样伴随 Full GC 一起出现(如
[GC (Promotion Failure)]),基本可断定碎片已影响分配能力 - 注意时间密度:1分钟内出现3次以上,说明碎片问题正在恶化
- 别只看有没有,要结合前后老年代使用量变化——例如
[PSOldGen: 850M->849M(1024M)],仅回收1MB,R值<0.001,就是典型“扫了也白扫”
盯紧老年代回收前后的差值与碎片率
Full GC后老年代占用下降极少,是碎片最直观的体现。用GC日志算两个数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 回收差值比:用回收前大小减去回收后大小,再除以回收前大小。结果<1%即高度可疑
-
隐含碎片线索:日志中若频繁出现
tenuring distribution或age table显示大量对象年龄为15(最大阈值),说明它们反复在Survivor间复制却无法晋升——不是因为该留,而是老年代“没地方收” - 配合工具验证:把gc.log上传到 GCEasy,重点看报告里的 Fragmentation %,>25%即属严重,>40%往往已临近崩溃
查大对象分配是否被反复拒绝
大对象(通常≥1MB)会直接尝试进入老年代。若日志中反复出现类似提示,就是碎片在“卡脖子”:
Allocation Failure: 12.4M object could not be allocated in old genG1EvacuationPause (mixed) … Promotion failed for humongous allocation- 尤其注意G1日志中的 humongous allocation 记录——G1对大对象有独立分区管理,频繁失败说明Humongous区碎片已满
- 结合
-XX:+PrintGCDetails中的survivor occupancy看:如果Survivor长期接近0,但Eden仍秒满,说明对象根本没机会活过一次Minor GC,直接被“挤”向老年代,加剧碎片
交叉验证元空间与类加载行为
类加载器泄漏虽不直接占堆,但会持续吃掉Metaspace,并间接挤压老年代可用空间。日志中要同步观察:
- Metaspace使用是否单向增长:如
[Metaspace: 120M->120M(1056M)]长期不变但数值偏高,可能旧ClassLoader未释放 - Full GC前是否有
Metadata GC Threshold触发,且之后Metaspace使用率未明显下降 - 配合
jstat -class <pid></pid>查 loaded 类数量是否持续上涨,unloaded 数量几乎为0
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










