30

我对 GC 算法有一些疑问:首先,当我们使用 、 等参数时UseSerialGC,我们指定了一个 GC 算法。他们每个人都可以在所有世代中进行GC,对吗?UseParallelGCUseParallelOldGC

例如,如果我使用java -XX:+UseSerialGC,所有代都将使用串行 GC 作为 GC 算法。

其次,我可以ParallelGC在老一代中使用并SerialGC在年轻一代中使用吗?

ParallelGC最后一个作为标题和有什么区别ParallelOldGC

4

4 回答 4

24

看看HotSpot VM 选项

-XX:+UseParallelGC = 使用并行垃圾收集进行清理。(在 1.4.1 中引入)。

-XX:+UseParallelOldGC = 对完整收集使用并行垃圾收集。启用此选项会自动设置 -XX:+UseParallelGC。(在 5.0 更新 6 中引入。)

其中 Scavenges = 年轻代 GC。

于 2011-06-04T12:42:50.620 回答
12

好吧,经过大量搜索和研究,我了解到如下,

-XX:+UseParallelGC - 这使得 GC 可以在年轻代中使用多个线程,但对于老年代/老年代仍然使用串行标记和紧凑算法。

-XX:+UseParallelOldGC - 这使 GC 能够在老年代/终身代中使用Parallel Mark 和 Compact算法。

让我们理解——

在年轻代中工作的算法和内存安排,如标记和复制、交换空间,由于多种原因不适用于老年代

低死亡率——在老一代中,“死亡率”明显低于年轻一代。在典型的 Java 应用程序中,大多数对象会很快消亡,而少数对象的寿命会更长。作为在年轻代中存活并提升到老年代的对象,可以观察到这些对象的寿命往往更长。与年轻一代相比,这导致老一代的死亡率非常低。

显着大小 -老一代明显大于年轻一代。因为年轻代很快被清理干净,所以相对较少的空间可用于许多短期对象(小年轻代)。在老一代中,对象随着时间的推移而积累。因此,老年代的空间一定比年轻一代(大老年代)多得多

分配少——老一代的分配比年轻一代少。这是因为在老年代中,只有当垃圾收集器将存活的对象从年轻代提升到老年代时才会出现对象。另一方面,在年轻代中,应用程序使用 new 生成的所有对象,即大部分分配,都发生在年轻代中。

考虑到这些差异,为年轻代选择了一种算法,该算法将尽快完成垃圾收集,因为它必须经常调用,因为它的死亡率很高[点 (1)]。此外,算法必须确保最有效的内存分配 [点 (3)] 是可能的,因为在年轻一代中分配了很多。年轻代上的标记和复制算法具有这些属性。

另一方面,这个算法对老一代没有意义。情况有所不同:垃圾收集器必须处理老一代中的许多对象[第 (2) 点],而且其中大部分还活着;只有一小部分变得无法访问并且可以释放[点 (1)]。如果垃圾收集器在每次垃圾收集时复制所有幸存的对象,就像它对标记和复制所做的那样,那么它将花费大量时间来复制它而不会获得太多收益。

因此标记和清除算法是在老年代进行的,这里什么都不复制,只是释放不可达的对象。由于该算法会导致堆碎片化,因此还考虑了标记和扫描算法的一种变体,其中在扫描阶段之后进行压缩,从而减少碎片。这种算法称为标记和压缩算法。

标记和紧凑算法可能非常耗时,因为它需要在后续阶段遍历对象图。

  1. 标记。
  2. 新位置的计算。
  3. 参考调整。
  4. 移动

计算新位置阶段,当它获得空闲空间时,会尝试找到一个可以移动到该空间的对象(碎片整理)。存储该对以供以后阶段使用。这会导致算法消耗更多的时间。

虽然标记和比较解决了一些特定于tenured generation的问题,但它有一些严重的问题,因为这是一个STW(Stop the world)事件,并且消耗大量时间,会严重影响应用程序。

老一代的替代算法

为了减少中断时间,已经考虑了串行标记和压缩算法的替代方案:

一种并行标记和压缩算法,它仍然锁存所有应用程序线程,但随后使用多个垃圾收集器线程处理标记和后续压缩。虽然这仍然是一种停止世界的方法,但在多核或多处理器机器上产生的暂停比串行标记和压缩算法更短。老一代的这种并行算法(称为“ParallelOld”)自 Java 5 Update 6 起就可用,并通过选项-XX: + UseParallelOldGC进行选择。

一种竞争性的标记和清除算法,它至少部分地与应用程序竞争而不停止其线程,并且偶尔需要短暂的停止世界阶段。这种并发的标记和清除算法(称为“CMS”)从 Java 1.4.1 开始就已经存在;它通过选项 -XX:+UseConcMarkSweepGC 打开。重要的是,这只是一个标记和扫描算法。没有发生压缩,导致已经讨论过的碎片问题。

因此,简而言之-XX: + UseParallelOldGC用于指示在使用Mark 和 Compact算法进行主要收集时使用多个线程。如果改为使用它,则次要或年轻收集是并行的,但主要收集仍然是单线程的。

我希望这个答案。

于 2018-07-05T09:18:15.567 回答
2

这是应用于 Java 堆的不同区域的两个 gc 策略,即新代和旧代。这是一个链接,有助于澄清哪些选项暗示其他选项。当您指定说 ParallelOldGC 或 ParNewGC 时,尤其是在开始了解您所得到的内容时,这很有帮助。 http://www.fasterj.com/articles/oraclecollectors1.shtml

于 2015-08-10T23:54:29.987 回答
2

来自 Oracle Java SE 8 文档:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html

并行收集器(也称为吞吐量收集器)并行执行次要收集,可以显着减少垃圾收集开销。它适用于在多处理器或多线程硬件上运行的中型到大型数据集的应用程序。在某些硬件和操作系统配置上默认选择并行收集器,或者可以使用选项显式启用-XX:+UseParallelGC

并行压缩是一项使并行收集器能够并行执行主要收集的功能。如果没有并行压缩,主要收集使用单个线程执行,这会显着限制可伸缩性。-XX:+UseParallelGC如果已指定选项,则默认启用并行压缩。关闭它的选项是-XX:-UseParallelOldGC

因此,如果您指定-XX:+UseParallelGC,默认情况下,major collection 也将使用多个线程完成。反之亦然,即如果您指定-XX:+UseParallelOldGC,次要收集也将使用多个线程完成。

于 2018-10-06T17:51:11.400 回答