-XX:+UseParallelGC和-XX:+UseParNewGC有什么区别?

96

它们是针对年轻代垃圾回收的算法。

第二种算法(UseParNewGC)会随着并发老年代垃圾回收(参见Java Concurrent and Parallel GC)自动激活,但两个并行算法之间有什么区别呢?

5个回答

128

经过大量搜索,我发现最好的解释来自Java性能调整网站中的问题月刊:1.4.1垃圾回收算法,2003年1月29日

年轻代垃圾回收算法

(原始)复制收集器(默认启用)。当此收集器启动时,所有应用程序线程都会停止,并且使用一个线程进行复制收集(这意味着即使在多CPU机器上也只有一个CPU)。这被称为全停顿集合,因为基本上JVM暂停了除收集完成外的所有内容。

并行复制收集器(使用-XX:+UseParNewGC启用)。与原始复制收集器类似,这是一个全停顿收集器。然而,该收集器将复制收集并行化到多个线程上,对于多CPU机器而言比原始单线程复制收集器更有效率(但对于单CPU机器则不是)。与原始单线程复制收集器相比,该算法可能将年轻代收集速度提高了等于可用CPU数量的因子。

并行清理收集器(使用-XX:UseParallelGC启用)。这类似于前面的并行复制收集器,但该算法针对多CPU机器上的千兆字节堆(超过10GB)进行了调整。该收集算法旨在最大化吞吐量并最小化暂停时间。它具有可选的自适应调整策略,可以自动调整堆空间大小。如果使用此收集器,则只能在老年代中使用原始标记清除收集器(即较新的老年代并发收集器不能与此年轻代收集器一起使用)。

从这些信息来看,主要区别(除了CMS合作外)似乎是UseParallelGC支持人体工程学而UseParNewGC不支持。


3
稍微更新的链接 http://www.fasterj.com/articles/oraclecollectors1.shtml - phunehehe
@phunehehe 谢谢你提供的链接!非常有帮助。 - The Student Soul

22

Parallel GC

  • XX:+UseParallelGC 使用并行垃圾回收进行scavenge。(自1.4.1版本起引入)
  • XX:+UseParallelOldGC 使用并行垃圾回收进行完整的垃圾回收。启用此选项将自动设置 -XX:+UseParallelGC。(自5.0更新6版引入)

UseParNewGC

UseParNewGC 在使用并发收集器时,使用年轻代复制收集器的并行版本(即如果在命令行上使用了-XX: + UseConcMarkSweepGC,则如果它在命令行上未明确设置,则标志UseParNewGC也将设置为true)。

也许最容易理解的是由Alexey Ragozin组合的垃圾回收算法。

<table border="1" style="width:100%">
  <tr>
    <td align="center">Young collector</td>
    <td align="center">Old collector</td>
    <td align="center">JVM option</td>
  </tr>
  <tr>
    <td>Serial (DefNew)</td>
    <td>Serial Mark-Sweep-Compact</td>
    <td>-XX:+UseSerialGC</td>
  </tr>
  <tr>
    <td>Parallel scavenge (PSYoungGen)</td>
    <td>Serial Mark-Sweep-Compact (PSOldGen)</td>
    <td>-XX:+UseParallelGC</td>
  </tr>
  <tr>
    <td>Parallel scavenge (PSYoungGen)</td>
    <td>Parallel Mark-Sweep-Compact (ParOldGen)</td>
    <td>-XX:+UseParallelOldGC</td>
  </tr>
  <tr>
    <td>Serial (DefNew)</td>
    <td>Concurrent Mark Sweep</td>
    <td>
      <p>-XX:+UseConcMarkSweepGC</p>
      <p>-XX:-UseParNewGC</p>
    </td>
  </tr>
  <tr>
    <td>Parallel (ParNew)</td>
    <td>Concurrent Mark Sweep</td>
    <td>
      <p>-XX:+UseConcMarkSweepGC</p>
      <p>-XX:+UseParNewGC</p>
    </td>
  </tr>
  <tr>
    <td colspan="2">G1</td>
    <td>-XX:+UseG1GC</td>
  </tr>
</table>

结论:

  1. 仅在需要对年轻代应用并行收集方法时应使用 -XX:+UseParallelGC(但仍需)使用串行标记-清除方法进行老年代收集。
  2. 当您需要在年轻代和老年代中同时应用并行收集方法时,请使用 -XX:+UseParallelOldGC(自动设置-XX:+UseParallelGC)。
  3. 当您需要对年轻代应用并行收集方法并且需要 CMS 方法作为您对老年代内存的收集方法时,请应用 -XX:+UseParNewGC 和 -XX:+UseConcMarkSweepGC。
  4. 不能同时使用-XX:+UseParallelGC 或 -XX:+UseParallelOldGC 和 -XX:+UseConcMarkSweepGC,因此如果您希望在年轻代中使用串行方法,则需要将 -XX:+UseParNewGC 与 CMS 配对使用,否则请明确使用 -XX:+UseSerialGC 或者 -XX:-UseParNewGC。

必须是 -XX:-UseParallelGC - Minas Mina
注意:结论#1不再正确。对于现代JVM,应用“-XX:+ UseParallelGC”会导致同时使用年轻代和老年代的并行GC。请参见https://bugs.openjdk.java.net/browse/JDK-6679764?focusedCommentId=12410139&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-12410139。 - turbanoff

15

UseParNewGC通常被称为“并行年轻代收集器”,在所有方面都与并行垃圾回收器(-XX:+ UseParallelGC)相同,但其更为复杂和高效。此外,它可以与“并发低暂停收集器”一起使用。

有关更多信息,请参见Java GC FAQ的第22个问题。

请注意,目前已知UseParNewGC存在一些已知的错误。


8
你知道有哪些已知的bug或者哪个JVM版本存在这些问题吗? - fglez

3
使用-XX:+UseParNewGC和-XX:+UseConcMarkSweepGC,与-XX:+UseParallelGC相比,会导致较高的暂停时间。这是因为将对象从年轻代提升到老年代需要运行最佳适配算法(由于老年代碎片),以查找此对象的地址。使用-XX:+UseParallelGC时不需要运行这样的算法,因为+UseParallelGC只能配置为MarkandCompact Collector,在该收集器中不存在碎片。

这是一个非常好的见解。你进行了任何测试来确认它吗? - fglez

0

我将尝试使用Oracle官方文档来回答这个问题:

-XX:+UseParNewGC 的目的是什么?

该参数的目的是启用年轻代中GC的并行线程。


-XX:+UseParallelGC v/s -XX:+UseParNewGC

  • -XX:+UseParallelGC 是并行收集器,而-XX:+UseParNewGC是并发年轻代收集器。
  • 并发年轻代收集器与并行垃圾收集器的目标类似,但实现方式不同。与并行收集器(­XX:+UseParallelGC)不同的是,这个并发年轻代收集器可以与收集年老代的并发低停顿收集器一起使用。


何时应启用/使用-XX: + UseParNewGC?

默认情况下,此选项已禁用,并且当设置-XX: + UseConcMarkSweepGC选项时,它会自动启用。在JDK 8中,使用-XX: + UseParNewGC选项而不使用-XX: + UseConcMarkSweepGC选项已被弃用。


总结

这个参数的整个目的是为了在年轻代中启用并行线程进行GC。在Java 8中,如果不使用CMS收集器(-XX:+UseConcMarkSweepGC),则使用此参数已被弃用;而在Java 9中,此参数本身也已被弃用,因为此参数只能与CMS收集器一起使用,而CMS收集器本身在Java 9中已被弃用。

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