为什么Java需要多个垃圾收集器?

30

我在我的电脑上启动的每个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]

我假设它们有重叠的池。当使用相同的池(Eden,survivor,old gen)时,两个垃圾收集器如何协同工作?是否没有对象在池之间移动(例如在调用第二个算法时从一个survivor到另一个survivor的移动)?即使不是这样,为什么我们需要每个池多个收集器?
我已阅读此GC文章。他们提到针对不同的major和minor GC使用不同的收集器,但似乎没有提到在同一池中使用多个收集器。

有不同的收集器来处理不同的代际,这有什么奇怪的呢? - Mikhail
我可以理解为不同的代使用不同的收集器,但是这里似乎有多个收集器用于同一代。那么这是如何工作的呢? - Aditya
主要的集合清理整个堆,而不仅仅是老年代。 - Mikhail
2个回答

46
我假设它们有重叠的池子。

这个假设是错误的。PS Scavenge将用于年轻代(eden,survivor),而PS MarkSweep将用于老年代。唯一的“重叠”是PS Scavenge会将对象移动到老年代,一旦它们存在一段时间,然后让PS MarkSweep处理它们。

为不同池使用不同的垃圾回收器的好处在于,适用于eden池中对象的算法未必适用于老年代对象。

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

至于“major”收集,当没有空间将对象移入老年代时发生,Sun的这篇(尽管有点陈旧)白皮书说:

...不运行年轻代收集算法。相反,整个堆上使用老年代收集算法。


我在搜索时遇到了这篇文章,但由于它是针对JDK 1.7.0_04的,而我正在使用1.6,所以我没有详细阅读。谢谢,我会阅读它并看看它是否回答了我的问题。 - Aditya
在进行整个堆的主要垃圾回收(运行整个堆的垃圾回收)期间,伊甸园空间中使用哪个收集器?请标明正确答案。 - Aditya
1
@gap_j - 我添加了一些关于我在一份旧白皮书中发现的主要集合的内容,希望这些仍然是正确的。 - David Webb
PS MarkSweep将收集整个堆的年轻代和老年代。并发标记扫描算法不会触及年轻代空间。 - Alexey Ragozin

1

根据您提供的文章:

通常,在每次小型收集期间,从年轻一代中存活下来的对象的一部分被移动到终身一代。最终,终身一代将填满并必须进行收集,导致整个堆被收集。主要收集通常比次要收集持续时间更长,因为涉及的对象数量显着更多。


主要的垃圾收集器也会进行小型GC。在进行主要的垃圾收集时,并不指定用于小型GC的收集器。 - Aditya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接