什么是 Java 中的“单代”垃圾收集器?

问题描述

在阅读有关 ZGC 的文章时,我注意到它吹嘘自己是“单代垃圾收集器”,但我很少看到有关该术语确切含义的任何详细信息。

普通分代 GC

我熟悉伊甸园、幸存者空间、托儿所、临终关怀、元空间、permgen、僵尸对象、诺亚方舟和老年之家,所以我不需要解释并发标记扫描(CMS GC)或垃圾优先(G1 GC)算法工作。我的理解是这些都是多代的,我很擅长。

就我个人而言,我一直喜欢能够通过 Java Mission Control 并查看一个对象经历了多少代 GC 周期。这对于解决内存泄漏或 GC 问题总是很有帮助。

单代与多代 GC

那么“单代”垃圾收集器究竟是什么,它与当前通过 CMS 和 G1 中的多个垃圾收集周期跟踪对象的方式有何不同?

解决方法

tl;博士

ZGC 有很多值得吹嘘的地方,但单代产品不在其中。

计划添加多代人作为未来的改进。

详情

一些垃圾收集器实现区分新对象和旧对象,“年轻代”与“老年代”。目标是让程序员创建短期对象的成本更低,因为它们将被更快、更有效地处理以释放内存。

ZGC 不会“吹嘘”自己是单代人。恰恰相反,该团队表示他们希望在 ZGC 的未来版本中添加分代功能。请参阅 Oracle 的 Per Liden 的演讲的这一部分中的讨论(等待几秒钟以查看新幻灯片“Generational ZGC”):https://youtu.be/88E86quLmQA

有关世代的更多信息,请参阅此问题:Java heap terminology: young,old and permanent generations?

,

您确实知道细节,但是您知道为什么发明了分代垃圾收集器吗?具体来说,为什么 G1GC 是代际的?

当时的想法是扫描整个堆很昂贵,昂贵意味着 STW。事实上,G1 以非代际(或您称之为单代)的方式开始它的生命,但是记住集合的大小和它们遍历它们的时间,触发它成为代际。存在“世代”的事实 + G1 在单个循环中扫描所有年轻区域的事实(或者更好地说,如果它“承诺”在某个循环开始时扫描一些 X 数量的年轻区域 -它必须全部扫描),这意味着您不需要记忆集合在年轻空间中在它们之间建立连接(卡片表也小得多)。

对于您直接的问题,ZGC(以及 Shenandoah)不会“跟踪”对象存活了多少个周期,他们不需要这样做,因为他们没有世代,因此无需将对象移动到“旧”中的某处以“稍后”进行扫描。他们在每个周期扫描整个堆。它们同时进行(以一种非常有趣的方式),因此目前根本没有必要让它们代代相传。