JVM G1垃圾回收器总结

G1垃圾收集器

G1是一个面向服务端的JVM垃圾收集器,适用于多核处理器、大内存容量的服务端系统。 它满足短时间停顿的同时达到一个高的吞吐量。从JDK 9开始,G1成为默认的垃圾回收器。
当应用有以下任何一种特性时非常适合用G1:

  • Full GC持续时间太长或者太频繁
  • 对象的创建速率和存活率变动很大
  • 应用不希望停顿时间长(长于0.5s甚至1s)

G1对Heap的划分


G1按固定大小把内存划分为很多小区域(region),这个堆大概有2000多块;在逻辑上,某些小区域构成Eden,某些构成Survivor,某些构成老年代,这些小区域物理上是不相连的,并且构成新生代和老年代的区域可以动态改变。
可以通过命令行参数-XX:NewRatio=n来配置新生代与老年代的比例,默认为2,即比例为2:1;-XX:SurvivorRatio=n则可以配置Eden与Survivor的比例,默认为8。

Young GC

当Eden区的空间占满之后,会触发Young GC,G1将Eden和Survivor中存活的对象拷贝到Survivor,或者直接晋升到Old Region中。Young GC的执行是多线程并发的,期间会停顿所有的用户线程(STW)。

Old GC

当堆空间的占用率达到一定阈值后会触发Old GC(阈值由命令参数-XX:InitiatingHeapOccupancyPercent设定,默认值45),Old GC分五个步骤完成:

初始标记(Initial Mark,STW)

对Survivor区域扫描,标记出可能拥有老年代对象引用的根区域(Root Region),该阶段附属于一次Young GC的最后阶段,所以是STW。在GC日志中会被记录为GC pause (young)(inital-mark)

根区域扫描(Root Region Scan)

从上一阶段标记的根区域中,标记所有拥有老年代对象引用的存活对象,这是一个并发的过程,而且必须在进行下一次Young GC之前完成

并发标记(Concurrent Marking)

从上一阶段标记的存活对象开始,并发地跟踪所有可达的老年代对象,期间可以被Young GC打断

最终标记(Remark,STW)

G1并行地跟踪在上面阶段经过更新的存活对象,找到未被标记的存活的对象,这是一个STW的阶段,会用到一个初始快照(SATB)算法。在此期间完全空闲的区域会被直接重置回收。

复制/清除(Copying/Cleanup,STW)

  • G1统计存活对象和完全空闲的区域,完全空闲区域将被重置回收
  • 执行清理RSet的操作
  • 将存活对象复制到新的未被占用的区域。执行这一步时可以只对新生代操作,这时G1将其记录为[GC pause (young)];也可对新生代和一部分老年代都进行处理,这时被记录为[GC Pause (mixed)],这些老年代要根据其“存活度”去选择。

G1相关的命令

java命令行参数

OptionDescription
-XX:+UseG1GCUse the Garbage First (G1) Collector
-XX:MaxGCPauseMillis=nSets a target for the maximum GC pause time. This is a soft goal, and the JVM will make its best effort to achieve it.
-XX:InitiatingHeapOccupancyPercent=nPercentage of the (entire) heap occupancy to start a concurrent GC cycle. It is used by GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap, not just one of the generations (e.g., G1). A value of 0 denotes ‘do constant GC cycles’. The default value is 45.
-XX:NewRatio=nRatio of new/old generation sizes. The default value is 2.
-XX:SurvivorRatio=nRatio of eden/survivor space size. The default value is 8.
-XX:MaxTenuringThreshold=nMaximum value for tenuring threshold. The default value is 15.
-XX:ParallelGCThreads=nSets the number of threads used during parallel phases of the garbage collectors. The default value varies with the platform on which the JVM is running.
-XX:ConcGCThreads=nNumber of threads concurrent garbage collectors will use. The default value varies with the platform on which the JVM is running.
-XX:G1ReservePercent=nSets the amount of heap that is reserved as a false ceiling to reduce the possibility of promotion failure. The default value is 10.
-XX:G1HeapRegionSize=nWith G1 the Java heap is subdivided into uniformly sized regions. This sets the size of the individual sub-divisions. The default value of this parameter is determined ergonomically based upon heap size. The minimum value is 1Mb and the maximum value is 32Mb.

查看JVM默认的垃圾回收器

1
java -XX:+PrintCommandLineFlags -version

1
2
3
4
-XX:G1ConcRefinementThreads=4 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC 
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)

查看JVM当前堆情况

1
jmap -heap pid 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
jmap -heap  20932
Attaching to process ID 20932, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11

using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 4164943872 (3972.0MB)
NewSize = 1363144 (1.2999954223632812MB)
MaxNewSize = 2498756608 (2383.0MB)
OldSize = 5452592 (5.1999969482421875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
regions = 3972
capacity = 4164943872 (3972.0MB)
used = 2132264664 (2033.4860458374023MB)
free = 2032679208 (1938.5139541625977MB)
51.19551978442604% used
G1 Young Generation:
Eden Space:
regions = 829
capacity = 2317352960 (2210.0MB)
used = 869269504 (829.0MB)
free = 1448083456 (1381.0MB)
37.51131221719457% used
Survivor Space:
regions = 9
capacity = 9437184 (9.0MB)
used = 9437184 (9.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 1254
capacity = 1741684736 (1661.0MB)
used = 1253557976 (1195.4860458374023MB)
free = 488126760 (465.51395416259766MB)
71.9738739215775% used

19747 interned Strings occupying 1885184 bytes.

参考资料