Java 7(JDK 7)垃圾回收和G1文档

82

Java 7 已经发布了一段时间,但我找不到关于配置 垃圾回收器 的好资源,特别是新的 G1 回收器

我的问题:

  1. G1 是 Java 7 中的默认收集器吗?如果不是,我该如何激活 G1?
  2. Java 7 中 g1 有哪些可选设置?
  3. 在 Java 7 中是否对其他收集器(如 cmsparallel collector)进行了更改?
  4. 在哪里可以找到关于 Java 7 垃圾回收的良好文档?

6
使用G1垃圾收集器入门也提供了最佳实践的概述。 - John McCarthy
1
http://www.oracle.com/technetwork/articles/java/g1gc-1984535.html - emkays
8个回答

47

G1垃圾收集器不是我安装的Java版本1.7.0_01的默认选项。您可以通过使用一些额外的命令行选项自行查看:

> java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -version
-XX:InitialHeapSize=132304640 -XX:MaxHeapSize=2116874240 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Heap
 PSYoungGen      total 37696K, used 1293K [0x00000007d5eb0000, 0x00000007d88c0000, 0x0000000800000000)
  eden space 32320K, 4% used [0x00000007d5eb0000,0x00000007d5ff3408,0x00000007d7e40000)
  from space 5376K, 0% used [0x00000007d8380000,0x00000007d8380000,0x00000007d88c0000)
  to   space 5376K, 0% used [0x00000007d7e40000,0x00000007d7e40000,0x00000007d8380000)
 PSOldGen        total 86144K, used 0K [0x0000000781c00000, 0x0000000787020000, 0x00000007d5eb0000)
  object space 86144K, 0% used [0x0000000781c00000,0x0000000781c00000,0x0000000787020000)
 PSPermGen       total 21248K, used 2032K [0x000000077ca00000, 0x000000077dec0000, 0x0000000781c00000)
  object space 21248K, 9% used [0x000000077ca00000,0x000000077cbfc288,0x000000077dec0000)

现在你无需启用实验性选项即可开启G1垃圾收集器:

> java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseG1GC -version
-XX:InitialHeapSize=132304640 -XX:MaxHeapSize=2116874240 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Heap
 garbage-first heap   total 130048K, used 0K [0x000000077ca00000, 0x0000000784900000, 0x00000007fae00000)
  region size 1024K, 1 young (1024K), 0 survivors (0K)
 compacting perm gen  total 20480K, used 2032K [0x00000007fae00000, 0x00000007fc200000, 0x0000000800000000)
   the space 20480K,   9% used [0x00000007fae00000, 0x00000007faffc288, 0x00000007faffc400, 0x00000007fc200000)
No shared spaces configured.

我不知道你可以在哪里找到好的文档。


2
这在OSX上的1.7.0_09版本仍然有效。 - Age Mooij
直接从Oracle网站获取的Linux/amd64上的Oracle JDK 7u17不适用此规则。它说:“-XX:+UseParallelGC”。 - user1050755

31

1
服务器至少需要2核2GB RAM或更多。详细信息可通过http://hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/0d82bf449a61/src/获得--查看文件./share/tools/launcher/java.c和./share/vm/runtime/os.cpp。 - user1050755

22

是的,G1是Java 1.7 JVM中新的标准垃圾收集器。

在这里,您可以找到有关如何使用和配置新垃圾收集器的大量信息:

G1的使用 G1仍被视为实验性功能,可以通过以下两个参数启用:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

要设置GC暂停时间目标,请使用以下参数:

-XX:MaxGCPauseMillis =50(暂停时间目标为50ms)

使用G1时,可以指定一个时间间隔,在此间隔内GC暂停时间不应超过上述给定的时间:

-XX:GCPauseIntervalMillis =200(暂停间隔目标为200ms)

请注意,上述两个选项代表目标,而不是承诺或保证。它们可能在某些情况下很有效,但在其他情况下可能无效,而且GC可能无法遵守它们。

另外,可以显式指定年轻代的大小以影响疏散暂停时间:

-XX:+G1YoungGenSize=512m(表示512兆字节的年轻代)

G1还使用了类似幸存者空间的东西,自然而然地是一组(可能不连续的)区域。可以使用通常的参数指定它们的大小(例如,-XX:SurvivorRatio=6)。

最后,要发挥G1的全部潜力,请尝试设置这两个参数,它们默认情况下被禁用,因为它们可能会发现一个罕见的竞争条件:

-XX:+G1ParallelRSetUpdatingEnabled -XX:+G1ParallelRSetScanningEnabled

还有一件需要注意的事情是,与其他垃圾收集器相比,G1非常冗长。

当设置-XX:+PrintGCDetails时,HotSpot GC将会出现。这是因为它会打印每个GC线程的时间以及其他有助于分析和故障排除的信息。如果您需要更简洁的GC日志,请切换到使用-verbosegc(尽管建议获得更详细的GC日志)。

我也发现此文对了解G1的内部非常有帮助。

更多信息在这里


6
我看过这些资料。但第一篇文章是关于JDK 6中实验选项G1的,其他文章则涉及JDK 7的测试版本并且至少有1年历史。我正在寻找更加更新的信息或者来自Oracle或JDK团队官方文献的资料。 - Florakel

13
1. G1是Java 7中的默认收集器吗(...)?
这个Java 5页面上的规则在Java 7(以及据我所知,Java 8)仍然适用:
引用: 在运行服务器VM的服务器级别机器上,垃圾收集器(GC)已从以前的串行收集器(-XX:+UseSerialGC)更改为并行收集器(-XX:+UseParallelGC)。
但也要考虑以下内容:
  • 64位JVM不带有-client VM,因此始终是"服务器级别"
  • 自Java 7以来,使用-XX:+UseParallelGC(无论是设置还是隐含)还隐含地使用-XX:+UseParallelOldGC(即除非显式禁用)
例如,如果在Windows x64上运行...
  • Java 7 64位,默认情况下使用并行GC(适用于年轻代和老年代)。
  • Java 8 32位,默认情况下使用串行GC(适用于年轻代和老年代)。

1. (...) 如何激活G1垃圾收集器?

从Java 7开始,只需使用-XX:+UseG1GC。也许你还会对以下情况感兴趣:

如果应用程序具有以下特点,那么目前使用CMS或ParallelOld垃圾收集器的应用程序切换到G1将会受益。

  • Java堆中超过50%的空间被活动数据占用。
  • 对象分配或提升的速率变化较大。
  • 不希望出现长时间的垃圾收集或压缩暂停(超过0.5到1秒)。

2. Java 7中G1有哪些可选设置?

我自己没有使用过G1,但我了解到它遵循了与其他并行收集器调优相同的基本“吞吐量/人体工程学”标志。根据我对并行GC的经验,-XX:GCTimeRatio是提供预期的速度-内存权衡的关键因素。个人经验可能有所不同。

G1的特定选项在这里列出。

3. Java 7中的cms或并行收集器有变化吗?

不知道,但是...

G1计划作为并发标记-清除收集器(CMS)的长期替代品。

4. 在Java 7中,我在哪里可以找到关于垃圾回收的好文档?

http://www.oracle.com/technetwork/java/javase/tech/index-jsp-140228.html

一些深入阅读是必要的,但如果你需要进行一些调整,那么这段时间是值得的。特别有见地的是:垃圾收集器的人体工程学

11

1. Java 7中G1是默认收集器吗?如果不是,如何激活G1?

G1不是Java 7中的默认收集器。使用-XX:+UseG1GC可以启用G1GC。

2. Java7中G1有哪些可选设置?

有很多。请查看Oracle文档页面以获取完整信息。

G1 GC是一种自适应垃圾收集器,具有默认值,可以在不修改的情况下有效地工作。

因此,定制关键参数

-XX:MaxGCPauseMillis
-XX:G1HeapRegionSize
-XX:ParallelGCThreads
-XX:ConcGCThreads

并将所有其他参数保留为默认值

您已重新配置了许多G1GC参数,如果按照上述文档页面操作,则不需要这些参数。请与上述建议进行交叉检查,特别是关于基于CPU核心的ParallelGCThreadsConcGCThreads。删除不必要参数的重新配置。

年轻代大小:避免使用-Xmn选项-XX:NewRatio显式设置年轻代大小。固定年轻代大小会覆盖目标暂停时间目标

3. 是否对Java 7中的其他收集器(如cms或并行收集器)进行了任何更改?

Java 7有一些变化。请参阅oracle release notes页面。

4. 在Java 7中,我在哪里可以找到有关垃圾回收的良好文档?

请参考Oracle教程页面


3

在JDK 1.7.0_02中,G1不是默认的垃圾收集器。 默认的垃圾收集器取决于机器的类别。 如果机器是服务器类,则默认垃圾收集器为吞吐量收集器。 如果机器是客户端类,则默认垃圾收集器为串行收集器。


1
我认为这是完全正确的。Java 5 reference,仍然有效。在Windows系统(32/64位)上:运行Java 32位(5..8)>>默认情况下使用Serial GC。运行Java 64位(5..6)>>默认情况下使用ParallelGC(仅Young gen)。运行Java 64位(7..8)>>默认情况下使用ParallelOldGC(并行Young和Old)。Java 7更改参考,最终'parallel' collector == 'throughput' collector' - Luke Usherwood
3
对于这个人第一次在SO上做出准确贡献的严厉回应。请注意,这也是他们的最后一次贡献。 - Luke Usherwood

2

0

默认情况下,您不需要真正使用G1收集器,因为它并不比其他收集器更好。它只适用于特殊目的。

在低延迟应用程序中,它比CMS略好,因为它具有稍微较短且更可预测的暂停时间。但是,换取的是吞吐量比CMS差得多。

因此,仅当延迟很重要而吞吐量完全不重要时才有用。如果两者都很重要,则应使用CMS。


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