为什么在Java中使用多个垃圾回收器?

2022-09-01 11:51:36

默认情况下,我在机器上启动的每个Java进程似乎都有两个垃圾回收器。我正在通过JConsole检查这一点。

示例 - 对于我当前运行的 Eclipse。

PS MarkSweep

Collection Count - 221
Collection Time - 102118
Memory Pool Names - java.lang.String[4]

PS 拾荒

Collection Count - 241
Collection Time - 2428
Memory Pool Names - java.lang.String[2]

我假设他们有重叠的池。当使用相同的池(伊甸园,幸存者,老一代)时,两个垃圾回收器如何协同工作?在池之间移动对象时,是否没有重叠(例如,当调用第二个算法时,从一个幸存者移动到另一个幸存者)?即使不是,为什么每个池需要多个收集器?

我已经阅读了有关GC的这篇文章。它们指的是对不同的主要和次要 GC 使用不同的收集器,但似乎没有参考在同一池上使用多个收集器。


答案 1

我假设他们有重叠的池。

这种假设是错误的。PS Scavenge将用于年轻(伊甸园,幸存者)一代,PS MarkSweep将用于老一代。唯一的“重叠”是,PS Scavenge会在对象存在一段时间后将对象移动到旧一代中,然后让PS MarkSweep处理它们。

为不同的池使用不同的垃圾回收器的好处是,适用于 eden 池中的对象的算法不一定适用于旧一代对象。

本文介绍了不同垃圾回收器协同工作的各种选项。

至于在没有空间将对象移动到旧一代时发生的“主要”集合,Sun的这份(诚然是旧的)白皮书说:

...年轻一代收集算法未运行。相反,旧一代收集算法用于整个堆。


答案 2

形成您提供的文章:

通常,在每个次要收藏期间,年轻一代的一部分幸存物品被转移到终身一代。最终,终身世代将填满并且必须收集,从而产生一个主要集合,其中收集了整个堆。主要集合的持续时间通常比次要集合长得多,因为涉及的对象数量要多得多。