在本节中,我们将学习 G1 收集器的各种命令行选项。
命令行的基本用法
如果要启用 G1 收集器,那么可以使用-XX:+UseG1GC
开关。
以下是一个启动 Java2Demo 程序的命令行示例,这个程序包含在下载得到的 JDK 演示和示例程序包之中:
java -Xmx50m -Xms50m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar
c:\javademos\demo\jfc\Java2D\Java2demo.jar
关键的命令行开关
-
-XX:+UseG1GC:告诉 JVM 使用 G1 垃圾收集器。
-
-XX:MaxGCPauseMillis=200:设置 GC 停顿时间的最大目标值。这不是一个硬性目标,JVM 将尽最大努力达成这个目标。因此,有时候并不能满足目标停顿时间。默认值为 200 毫秒。
-
-XX:InitiatingHeapOccupancyPercent=45:启动并发 GC 周期的(整个)堆内存占用率的百分比阈值。G1 收集器会根据整个堆内存的占用情况,而不是某个年代的占用情况,来触发一次并发的 GC 周期。若取值为 0,则表示“执行常量 GC 周期”。默认值为 45(也就是说,堆内存的占用率为 45%)。
最佳实践
以下是一些在使用 G1 收集器时应该遵循的最佳实践。
不要设置年轻代的大小
如果通过-Xmn
选项来显式地设置年轻代的大小,那么就会干预 G1 收集器的默认行为。
- G1 将不再会遵守垃圾收集的停顿时间目标。因此,大体上来说,设置年轻代的大小将会禁用停顿时间目标。
- G1 不再能够根据需要扩展和缩减年轻代的内存空间。因为大小已经固定了,所以就不能改变大小。
响应时间的指标
应该设置XX:MaxGCPauseMillis=<N>
选项,而不应该使用平均响应时间(ART)作为性能指标,这个设置值能够满足 90% 或更高的目标时间。这就意味着,在发起请求的所有用户中,至少有 90% 的用户经历的响应时间不会高于目标时间。注意,停顿时间只是一个目标,并不总是能够保证满足的。
什么是排空失败?
在垃圾收集期间,如果 JVM 在处理幸存对象和晋升对象时耗尽堆内存区域,那么便会发生晋升失败错误。因为堆内存已经达到最大容量,所以不能扩展容量。当使用-XX:+PrintGCDetails
开关时,这种错误在 GC 日志中表示为to-space overflow
。这样会付出昂贵的代价!
- 由于必须释放内存空间,因此 GC 仍然需要继续运行。
- 未能成功复制的对象必须就地老年化。
- 对 CSet 中的堆内存区域的 RSet 进行的任何更新都必须重新生成。
- 所有这些步骤的代价都非常昂贵!
如何避免排空失败
为了避免排空失败,可以考虑以下选项:
- 增加堆内存的大小:
- 增加
-XX:G1ReservePercent=n
选项的值,默认值为10。 - G1 会创建一个错误最高上限,试图预留一些备用的空闲内存,以防需要更多的“to-space”空间。
- 增加
- 更早地启动标记周期。
- 使用
-XX:ConcGCThreads=n
选项,增加标记线程的数量。
G1 垃圾收集器完整的命令行开关列表
以下是 G1 垃圾收集器完整的命令行开关列表。注意,你应该遵循上文强调的最佳实践。
选项和默认值 | 描述 |
---|---|
-XX:+UseG1GC | 使用垃圾优先(G1)收集器。 |
-XX:MaxGCPauseMillis=n | 设置 GC 停顿时间的最大目标值。这不是一个硬性目标,JVM 将尽最大努力达成这个目标。 |
-XX:InitiatingHeapOccupancyPercent=n | 启动并发 GC 周期的(整个)堆内存占用率的百分比阈值。垃圾收集器(例如:G1)会根据整个堆内存的占用情况,而不是某个年代的占用情况,来触发一次并发的 GC 周期。若取值为 0,则表示“执行常量 GC 周期”。默认值为 45。 |
-XX:NewRatio=n | 新生代和老年代的大小比率。默认值为 2。 |
-XX:SurvivorRatio=n | Eden 区和 Survivor 区的大小比率。默认值为 8。 |
-XX:MaxTenuringThreshold=n | 对象晋升至老年代的最大年龄阈值。默认值为 15。 |
-XX:ParallelGCThreads=n | 在并行阶段期间,垃圾收集器能够使用的线程数量。默认值会随着 JVM 的运行平台变化而变化。 |
-XX:ConcGCThreads=n | 并发垃圾收集器将会使用的线程数量。默认值会随着 JVM 的运行平台变化而变化。 |
-XX:G1ReservePercent=n | 设置需要预留的堆内存总量,可以作为 GC 的错误最高上限,以便于减少晋升失败的发生概率。默认值为 10。 |
-XX:G1HeapRegionSize=n | G1 收集器会将 Java 的堆内存分割成若干个大小相同的区域。这个选项可以设置各个子区域的大小。JVM 会根据堆内存的大小自动确定这个参数的默认值。最小值为 1Mb,最大值为 32Mb。 |