跳到正文
Elaine Blog
返回

GC 基础与三色标记

JVM 与性能

GC 回收的是从根集合不可达的对象,不是“引用计数变成零”的对象。现代收集器还必须在应用线程继续修改对象图时保持 标记正确,因此需要暂停、写屏障和并发协议协作。

Table of contents

Open Table of contents

从可达性开始

GC Roots 是可达性分析起点,常见来源包括线程栈中的引用、静态字段、JNI 引用和 JVM 内部结构。从根出发能遍历到的 对象是存活对象,其余对象才有资格回收。

循环引用不会阻止可达性 GC:若两个对象只互相引用,但从任何根都无法到达,它们仍可一起回收。System.gc() 只是显式 请求,也不证明某个对象立即被回收。

为什么需要 Stop-The-World

**STW(Stop-The-World)**表示 JVM 在某个阶段暂停应用线程。根扫描、对象转移或重新映射等工作需要一致视图。并发 收集器能把大量工作与应用并行执行,但通常仍有短暂停顿;“并发 GC”不等于“零暂停”。

应用线程在 GC 文档中常叫 Mutator(变更者),因为它持续改变对象图。停顿时间还受线程数量、根集合、卡表扫描、 对象复制和操作系统调度影响,不只取决于堆大小。

三色标记是推理模型

并发标记常用三种颜色描述状态:

应用线程可能在 GC 扫描后把黑对象指向白对象,同时删除灰对象到该白对象的旧引用。若收集器没有记录这次变化,存活 对象可能被误判为垃圾。

**写屏障(Write Barrier)**是在引用写入前后执行的一小段 JVM 逻辑,用于维护卡表、记忆集或并发标记队列。它不是 Java 的内存屏障,也不是业务代码中的锁。

用日志观察收集阶段

运行可控分配实验:

java -Xms128m -Xmx128m -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags \
  -cp target/classes dev.elaine.jvmlab.GcPressureSample 10

检查日志:

grep -E 'Pause|Concurrent|Safepoint' gc.log | head -n 30

你会看到暂停和并发阶段,但具体名称取决于收集器。分析时把暂停持续时间、发生频率、回收前后堆占用和分配速率一起看, 不能只挑最长一行。

分代假设

许多应用中的多数对象存活时间很短。分代收集利用这项经验,把新对象集中在年轻代并频繁回收;长期存活对象进入老年代。 这是优化假设,不是 Java 对象生命周期保证。缓存、批处理和大对象会改变存活分布。

Oracle 的 JDK 25 GC 实现说明 给出了分代收集和性能度量的官方定义。

下一步

阅读CMS、G1、ZGC 与现代收集器选型,把暂停和吞吐目标转换成 收集器选择。


分享这篇文章:

上一篇
解释执行、JIT、分层编译与反优化
下一篇
CMS、G1、ZGC 与现代收集器选型