gc日志不直接输出“对象存活率”,但可通过回收前后内存使用量(如4418k→256k)计算字节级存活比例≈5.8%,反映内存留存率而非对象个数;需按gc类型匹配对应区域(如young gc看年轻代、full gc看整个堆),对象数量需借助gcviewer或jfr等工具分析。

GC 日志本身不直接输出“对象存活率”这个百分比数值,但可以通过日志中关键内存区域的前后大小变化,手动推算出某次 GC 后的存活对象所占堆空间比例(即广义上的“存活率”)。这个值反映的是该次回收动作中,有多少已分配内存被保留下来,而非被清理掉。
看懂日志中的核心字段
典型 GC 日志片段如:
0.193: [GC 4418K->256K(61504K), 0.0046018 secs]- 4418K:GC 开始前,整个新生代(或当前收集区域)已使用的内存大小(即“回收前占用”)
- 256K:GC 结束后,该区域剩余的、仍被存活对象占用的内存大小(即“回收后占用”)
- (61504K):该区域的总容量(通常可忽略,用于参考上限)
计算单次 GC 的内存级存活率
用回收后的使用量除以回收前的使用量,即可得到该次 GC 操作后,该区域中内存层面的存活比例:
存活率 ≈ 256K ÷ 4418K ≈ 5.8%这意味着本次 GC 清理掉了约 94.2% 的内存,仅约 5.8% 的对象(或其占用空间)被判定为存活并保留下来。
注意:这不是对象个数的存活率,而是字节级内存占用的留存比例。大对象会显著拉高该值,小对象密集则可能拉低。
区分不同 GC 类型对应区域
存活率的计算需匹配 GC 类型和作用区域:
-
Young GC(Minor GC):关注 “年轻代使用量 → 回收后年轻代使用量”,例如
ParNew: 12345K->876K,按此计算 -
Full GC:若日志显示整个堆的变化(如
Full GC 123456K->45678K),则代表整个堆的存活内存占比 - 如果日志分代显示更细(如 CMS 或 G1),要定位到具体区域字段,比如
[GC (Allocation Failure) 20480K->10240K(30720K)]中的前后值即对应 Eden 区或整个年轻代
为什么不能直接等于“对象个数存活率”?
因为 JVM 不在 GC 日志里记录对象数量。一个 2MB 的大数组和一百个 16B 的 Integer 对象,可能共占 2MB 内存,但对象个数差上百倍。日志只反映内存水位,不反映实例数量。若需统计对象数量级行为,需配合 -XX:+PrintGCDetails + -XX:+PrintGCTimeStamps,再用工具(如 GCViewer、GCEasy)解析,或启用 JFR(Java Flight Recorder)做深度分析。










