G1上的Java 7(JDK 7)垃圾收集和文档


81

Java 7已经出现了一段时间,但是我在垃圾收集器(尤其是新的G1收集器)的配置上找不到任何好的资源。

我的问题:

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

6
G1垃圾收集器入门还对最佳实践进行了很好的概述。
John McCarthy 2013年

Answers:


47

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

> 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

1
在Linux上的1.7.0_10上相同
Marc Polizzi

直接从Oracle网站获取的Linux / amd64上的Oracle JDK 7u17并非如此。它说-XX:+UseParallelGC
user1050755

31

甲骨文终于在Java 7 U4中将G1正式发布:http : //www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html

描述: http //docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html

命令行选项: http //www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#G1Options

不过,我不认为它是Java 7中的默认收集器。对于服务器,默认情况下是Java 6中的并行收集器。


1
服务器由2个内核和2 GB或更高的RAM定义。可以通过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 MB的年轻代)

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

最后,要使G1发挥最大作用,请尝试设置以下两个参数,这些参数当前默认处于禁用状态,因为它们可能会发现罕见的竞争状况:

-XX:+ G1ParallelRSetUpdatingEnabled -XX:+ G1ParallelRSetScanningEnabled

还有一点要注意的是,当设置了-XX:+ PrintGCDetails时,与其他HotSpot GC相比,G1非常冗长。这是因为它会打印每个GC线程的时间安排和其他信息,它们对于性能分析和故障排除非常有帮助。如果您想要更简洁的GC日志,请切换为使用-verbosegc(尽管建议获取更详细的GC日志)。

我也发现了这个文章中了解G1的内部件非常有帮助。

这里有更多信息。


6
我看过这些资源。但是第一篇文章是关于JDK 6中的G1的,当时它仍然是一个实验性的选择。其他文章是关于JDK 7的Beta版本以及至少1年的历史。我正在寻找Oracle或JDK团队的最新信息或官方文档。
Florakel

13

1. G1是Java 7中的默认收集器(...)

此Java 5页面上的规则仍适用于Java 7(以及AFAIK,Java 8):

在运行服务器VM的服务器计算机上,垃圾收集器(GC)已从以前的串行收集器(-XX:+ UseSerialGC)更改为并行收集器(-XX:+ UseParallelGC)。

但还要考虑:

  • 64位JVM不随-clientVM一起提供,因此始终是“服务器类”
  • 从Java 7开始,使用-XX:+ UseParallelGC(无论设置还是暗示)还暗含-XX:+ UseParallelOldGC(即,除非明确禁用)

例如,如果在Windows x64上运行...

  • Java 7 64位,默认情况下会获得Parallel GC(适用于年轻人和老年人)。
  • Java 8 32位,默认情况下获得串行GC(两代)

1.(...)如何激活G1?

从Java 7开始,-XX:+UseG1GC。也许还有趣的是何时您想要:

如果当前具有CMS或ParallelOld垃圾收集器运行的应用程序具有以下一个或多个特征,则将其切换到G1将非常有益。

  • 超过50%的Java堆被实时数据占用。
  • 对象分配率或提升率差异很大。
  • 不必要的长时间垃圾收集或压缩暂停(长于0.5到1秒)

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

我自己没有使用过G1,但是发现它遵循与用于调整其他并行收集器相同的基本“吞吐量/人体工程学”标志。根据我使用Parallel GC的经验,-XX:GCTimeRatio在提供预期的速度-内存权衡方面一直是至关重要的。YMMV。

G1特定选项在此处列出

3. Java 7中是否对(...)cms或并行收集器进行了更改?

不知道,但是...

G1计划作为并发标记扫描收集器(CMS)的长期替代产品

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

找到它可能很痛苦,不是吗?我发现的最好的“中心”页面可能是这个页面:

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

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


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

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

  1. g1在Java7中有哪些可选设置?

有许多。查看此oracle文章以获取完整信息。

G1 GC是一个自适应垃圾收集器,具有默认值,可使其无需修改即可高效工作。

由于这个原因,自定义关键参数

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

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

这是重要选项及其默认值的列表。该列表适用于最新的Java HotSpot VM(版本24)。您可以在JVM命令行上调整和调整G1 GC设置。

重要默认值:

-XX:G1HeapRegionSize=n

设置G1区域的大小。该值为2的幂,范围为1MB至32MB。目标是根据最小Java堆大小具有大约2048个区域。

-XX:MaxGCPauseMillis=200

为所需的最大暂停时间设置目标值。默认值为200毫秒。指定的值不适合您的堆大小。

-XX:G1NewSizePercent=5

设置要用作年轻代大小的最小值的堆百分比。默认值为Java堆的5%。

-XX:G1MaxNewSizePercent=60

设置堆大小的百分比,以用作年轻代大小的最大值。默认值为Java堆的60%。

-XX:ParallelGCThreads=n

设置STW工作线程的值。将n的值设置为逻辑处理器的数量。n的值与最多等于8的逻辑处理器的数量相同。

如果逻辑处理器多于八个,则将n的值设置为逻辑处理器的大约5/8。除较大的SPARC系统外,这在大多数情况下均有效,其中n的值大约为逻辑处理器的5/16。

-XX:ConcGCThreads=n

设置平行标记线的数量。将n设置为并行垃圾回收线程(ParallelGCThreads)数量的大约1/4。

-XX:InitiatingHeapOccupancyPercent=45

设置触发标记周期的Java堆占用阈值。默认占用率为整个Java堆的45%。

-XX:G1MixedGCLiveThresholdPercent=65

设置要包含在混合垃圾收集周期中的旧区域的占用阈值。默认入住率为65%

-XX:G1HeapWastePercent=10

设置您愿意浪费的堆百分比。当可回收百分比小于堆垃圾百分比时,Java HotSpot VM不会启动混合垃圾回收周期

-XX:G1MixedGCCountTarget=8

设置标记周期后混合垃圾回收的目标数量,以收集具有最多G1MixedGCLIveThresholdPercent个实时数据的旧区域。默认值为8个混合垃圾回收

-XX:G1OldCSetRegionThresholdPercent=10

设置在混合垃圾收集周期中要收集的旧区域数的上限。默认值为Java堆的10%

-XX:G1ReservePercent=10

设置保留内存的百分比以使其保持空闲状态,以减少空间溢出的风险。默认值为10%。当增加或减少百分比时,请确保将总Java堆调整为相同的数量。

您已经重新配置了许多G1GC参数,如果您遵循上述文档页面,则不需要这些参数。请与上述建议进行交叉检查,尤其是在ParallelGCThreadsConcGCThreads上基于您的CPU内核的上。删除不必要参数的重新配置。

推荐建议oracle的:

在评估和微调G1 GC时,请牢记以下建议:

  1. 年轻一代的大小:避免使用该-Xmn选项或任何其他相关选项(例如)明确设置年轻一代的大小-XX:NewRatio固定年轻一代的大小会覆盖目标暂停时间目标

  2. 暂停时间目标:当您评估或调整任何垃圾收集时,总会有延迟与吞吐量的权衡。G1 GC是具有统一暂停的增量垃圾收集器,但在应用程序线程上也有更多开销。G1 GC的吞吐量目标是90%的应用时间和10%的垃圾收集时间

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

Java 7进行了一些更改。请看一下本文。

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

请参阅有关gc和相关SE问题的oracle文档页面:

生产中的Java G1垃圾回收


3

jdk 1.7.0_02中没有G1不是默认的垃圾收集器。默认的垃圾收集器取决于计算机的类。如果计算机属于服务器类,则默认垃圾收集器为吞吐量收集器。如果计算机属于客户端类,则默认垃圾收集器为串行收集器。


1
我认为这是完全正确的。Java 5参考,仍然有效。在Windows系统(32/64)上:默认情况下运行Java 32位(5..8)>>串行GC。默认情况下运行Java 64位(5..6)>> ParallelGC(仅限Young gen)。默认情况下运行Java 64位(7..8)>> ParallelOldGC(并行的Young和Old)。Java 7更改的参考,最后是'parallel'收集器=='throughput'收集器”
Luke Usherwood

3
(对于此人的第一个准确的SO做出严厉的回应。我注意到这也是他们的最后一个。)
Luke Usherwood 2013年


0

默认情况下,您实际上并不想使用G1收集器,因为它并不比其他收集器好。它仅对特殊目的有用。

在低等待时间中,应用程序比CMS更好,因为它更短一些,并且暂停时间更可预测。作为交换,吞吐量要比CMS差得多。

因此,只有等待时间很重要才是好事,但是吞吐量根本不重要。如果两者都很重要,请继续使用CMS。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.