G1日志分析

1. 概述

来自对官方G1垃圾收集器的日志解释分析,官方地址:https://blogs.oracle.com/poonam/understanding-g1-gc-logs或https://blog.csdn.net/zhanggang807/article/details/46011341

2. 实例

代码和VM参数:

public class Test00 {

private static final int _1MB = 1024 * 1024;
    
    public static void main(String[] args) {
        byte[] b1 = new byte[6 * _1MB];
        byte[] b2 = new byte[4 * _1MB];
    }

}


-Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails  -XX:+UseG1GC
-XX:+UnlockDiagnosticVMOptions -XX:+G1PrintHeapRegions

这篇博客主要解释G1的日志,这些日志可以通过开启G1垃圾收集器的跟踪和诊断开关获取。通过PrintGCDetails可以获取最详细的GC日志。

 我们也可以通过开启UnlockDiagnositcVMOptions和G1PrintRegionLivenessInfo参数,可以在标记周期最后打印每个分区(Region)的占用情况和存活对象占用空间。

G1PrintHeapRegions可以打印分区的分配和回收信息。

我们通过JDK 1.7.0_04生成G1日志。

实例如下:这是典型G1的Evacuation Pause(转移暂停),在这个阶段存活的对象被从一个分区(年轻代或年轻代+老年代)拷贝到另一个分区。

这是一个STW,所有的应用线程停止在安全点。

0.522: [GC pause (young), 0.15877971 secs]

    这是一个转移暂停,距离进程启动的0.522秒开始,所有被转移的是年轻代分区,一共花费了0.15877971秒。

    转移暂停也可以是混合的,比如:1.730:[GC pause (mixed), 0.32714353 secs]此时分区包含所有的年轻代分区和部分老年代分区。

   [Parallel Time: 157.1 ms]
并行GC Worker线程的总耗时,下面缩进部分是worker线程的子任务
[GC Worker Start (ms): 522.1 522.2 522.2 522.2
每个worker线程的启动时间(距离jvm启动的时间)

Avg: 522.2, Min: 522.1, Max: 522.2, Diff: 0.1]
所有线程启动时间的avg,min,max,diff(下同,不赘述)

[Ext Root Scanning (ms): 1.6 1.5 1.6 1.9
每个线程扫描Roots(全局变量,寄存器,线程栈,vm数据结构)的时间

Avg: 1.7, Min: 1.5, Max: 1.9, Diff: 0.4] 同上
[Update RS (ms): 38.7 38.8 50.6 37.3
每个线程更新Remember Set(RSet)时间,RSet保存引用

Avg: 41.3, Min: 37.3, Max: 50.6, Diff: 13.3]
[Processed Buffers : 2 2 3 2
Sum: 9, Avg: 2, Min: 2, Max: 3, Diff: 1]
[Scan RS (ms): 9.9 9.7 0.0 9.7
扫描RSet的时间,每个分区的RSet包含指向分区的Card。这个阶段扫描CSet集合中所有指向分区的Card。

Avg: 7.3, Min: 0.0, Max: 9.9, Diff: 9.9]
[Object Copy (ms): 106.7 106.8 104.6 107.9
拷贝CSet集合里面所有分区存活对象到另一个分区的时间。

Avg: 106.5, Min: 104.6, Max: 107.9, Diff: 3.3]
[Termination (ms): 0.0 0.0 0.0 0.0
Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0]
[Termination Attempts : 1 4 4 6
Sum: 15, Avg: 3, Min: 1, Max: 6, Diff: 5]
[GC Worker End (ms): 679.1 679.1 679.1 679.1
每个线程的停止时间

Avg: 679.1, Min: 679.1, Max: 679.1, Diff: 0.1]
[GC Worker (ms): 156.9 157.0 156.9 156.9
每个线程的耗时

Avg: 156.9, Min: 156.9, Max: 157.0, Diff: 0.1]
[GC Worker Other (ms): 0.3 0.3 0.3 0.3
每个线程执行除了上面操作的其他任务的耗时

Avg: 0.3, Min: 0.3, Max: 0.3, Diff: 0.0]
[Clear CT: 0.1 ms]
串行清除Card Table的时间

[Other: 1.5 ms]
[Choose CSet: 0.0 ms] 为CSet选择Region的时间
[Ref Proc: 0.3 ms] 处理对象引用的时间
[Ref Enq: 0.0 ms] 引用入ReferenceQueues队列的时间
[Free CSet: 0.3 ms] 释放CSet时间
[Eden: 12M(12M)->0B(10M) Survivors: 0B->2048K Heap: 13M(64M)->9739K(64M)]
Eden在回收之前容量和占用都是12MB,回收之后占用为0,容量为13MB(有新的分区加入Eden)。
Survivor回收之后,占用从0变到2048KB,整个堆在回收之前占用和容量是14MB和64MB,回收之后是9739KB和64MB。
[Times: user=0.59 sys=0.02, real=0.16 secs]

 除了转移暂停,G1也执行concurrent-marking去获取分区存活数据。

1.416: [GC pause (young) (initial-mark), 0.62417980 secs] 
标记周期的第一个阶段:初始标记,标记所有的可达Roots,需要STW,在年轻代阶段运行
…....
2.042: [GC concurrent-root-region-scan-start]
自从初始标记之后的,root-region标记
2.067: [GC concurrent-root-region-scan-end, 0.0251507]
2.068: [GC concurrent-mark-start]
第二个阶段:并发标记
3.198: [GC concurrent-mark-reset-for-overflow]
表明全局标记栈有泄漏,并发标记检测到这个泄露,必须重置数据结构,然后重新标记
4.053: [GC concurrent-mark-end, 1.9849672 sec]
4.055: [GC remark 4.055: [GC ref-proc, 0.0000254 secs], 0.0030184 secs]
第三个阶段:重新标记,需要STW。ref-proc: 引用处理
[Times: user=0.00 sys=0.00, real=0.00 secs]
4.088: [GC cleanup 117M->106M(138M), 0.0015198 secs]
第四个阶段:清除,需要STW。堆大小是138MB,回收之前占用117MB,之后是106MB
[Times: user=0.00 sys=0.00, real=0.00 secs]
4.090: [GC concurrent-cleanup-start]
释放空Region
4.091: [GC concurrent-cleanup-end, 0.0002721]

通过-XX:+UnlockDiagnosticVMOptions和-XX:+G1PrintRegionLivenessInfo参数可以打印在清除阶段每个Region存活对象信息。

如下:    

[GC cleanup
### PHASE Post-Marking @ 0.151 清除阶段启动距离jvm启动的时间
### HEAP reserved: 0x00000000fec00000-0x0000000100000000 region-size: 1048576 每个Region的大小是1048576字节
###
### type address-range used prev-live next-live gc-eff remset code-roots

Region类型,Region地址范围,Region已使用量,相对于前一次标记周期存活字节,相对于当前标记周期存活字节,gc回收效率,remset, code-roots
### (bytes) (bytes) (bytes) (bytes/ms) (bytes) (bytes)
### HUMS 0x00000000fec00000-0x00000000fed00000 1048576 1048576 1048576 0.0 2896 16

HUMS:Humongous starts,存放大对象的开始Region

### HUMC 0x00000000fed00000-0x00000000fee00000 1048576 1048576 1048576 0.0 2896 16

HUMC:Humongous continues,存放大对象的continue Region
### HUMC 0x00000000fee00000-0x00000000fef00000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000fef00000-0x00000000ff000000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff000000-0x00000000ff100000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff100000-0x00000000ff200000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff200000-0x00000000ff300000 16 16 16 0.0 2896 16
### HUMS 0x00000000ff300000-0x00000000ff400000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff400000-0x00000000ff500000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff500000-0x00000000ff600000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff600000-0x00000000ff700000 1048576 1048576 1048576 0.0 2896 16
### HUMC 0x00000000ff700000-0x00000000ff800000 16 16 16 0.0 2896 16

### EDEN 0x03400000-0x03500000 20992 20992 20992 0.0

Eden Region

### OLD 0x02f00000-0x03000000 1048576 1038592 1038592 0.0

老年代Region,总的使用量1048576byte,按照标记周期活跃数据是1038592字节,相对当前标记周期的活跃数据也是1038592字节。GC效率计算结果为0。
### FREE 0x00000000ff800000-0x00000000ff900000 0 0 0 0.0 2896 16

未使用的Region
### FREE 0x00000000ff900000-0x00000000ffa00000 0 0 0 0.0 2896 16
### FREE 0x00000000ffa00000-0x00000000ffb00000 0 0 0 0.0 2896 16
### FREE 0x00000000ffb00000-0x00000000ffc00000 0 0 0 0.0 2896 16
### FREE 0x00000000ffc00000-0x00000000ffd00000 0 0 0 0.0 2896 16
### FREE 0x00000000ffd00000-0x00000000ffe00000 0 0 0 0.0 2896 16
### SURV 0x00000000ffe00000-0x00000000fff00000 733280 733280 733280 0.0 3144 264

Survivor Region
### FREE 0x00000000fff00000-0x0000000100000000 0 0 0 0.0 2896 16
###
### SUMMARY capacity: 20.00 MB used: 10.70 MB / 53.50 % prev-live: 10.70 MB / 53.50 % next-live: 10.70 MB / 53.50 % remset: 0.06 MB code-roots: 0.00 MB

G1的堆大小为20MB,使用了10.70MB,占比53.50%;之前标记的活跃数据是10.70MB,占比53.50%;当次标记存活对象10.70MB,占比53.50%。
### PHASE Post-Sorting @ 0.152
### HEAP reserved: 0x00000000fec00000-0x0000000100000000 region-size: 1048576
###
### type address-range used prev-live next-live gc-eff remset code-roots
### (bytes) (bytes) (bytes) (bytes/ms) (bytes) (bytes)
###
### SUMMARY capacity: 0.00 MB used: 0.00 MB / 0.00 % prev-live: 0.00 MB / 0.00 % next-live: 0.00 MB / 0.00 % remset: 0.00 MB code-roots: 0.00 MB

10M->10M(20M), 0.0008271 secs]

-XX:+UnlockDiagnosticVMOptions和-XX:+G1PrintHeapRegions记录Region相关事件(Region提交,分配,回收)。

如下:

 G1HR COMMIT [0x00000000fec00000,0x00000000fed00000]

 commit/uncommit事件,COMMIT 事件总是按顺序生成,比如下一个COMMIT 事件总会是未提交区域的低地址。
 G1HR COMMIT [0x00000000fed00000,0x00000000fee00000]
 G1HR COMMIT [0x00000000fee00000,0x00000000fef00000]
 G1HR COMMIT [0x00000000fef00000,0x00000000ff000000]
 G1HR COMMIT [0x00000000ff000000,0x00000000ff100000]
 G1HR COMMIT [0x00000000ff100000,0x00000000ff200000]
 G1HR COMMIT [0x00000000ff200000,0x00000000ff300000]
 G1HR COMMIT [0x00000000ff300000,0x00000000ff400000]
 G1HR COMMIT [0x00000000ff400000,0x00000000ff500000]
 G1HR COMMIT [0x00000000ff500000,0x00000000ff600000]
 G1HR COMMIT [0x00000000ff600000,0x00000000ff700000]
 G1HR COMMIT [0x00000000ff700000,0x00000000ff800000]
 G1HR COMMIT [0x00000000ff800000,0x00000000ff900000]
 G1HR COMMIT [0x00000000ff900000,0x00000000ffa00000]
 G1HR COMMIT [0x00000000ffa00000,0x00000000ffb00000]
 G1HR COMMIT [0x00000000ffb00000,0x00000000ffc00000]
 G1HR COMMIT [0x00000000ffc00000,0x00000000ffd00000]
 G1HR COMMIT [0x00000000ffd00000,0x00000000ffe00000]
 G1HR COMMIT [0x00000000ffe00000,0x00000000fff00000]
 G1HR COMMIT [0x00000000fff00000,0x0000000100000000]
 G1HR ALLOC(Eden) 0x00000000fff00000

 Region分配事件
 G1HR ALLOC(StartsH) 0x00000000fec00000 0x00000000fed00000

 Regions存储大对象
 G1HR ALLOC(ContinuesH) 0x00000000fed00000 0x00000000fee00000
 G1HR ALLOC(ContinuesH) 0x00000000fee00000 0x00000000fef00000
 G1HR ALLOC(ContinuesH) 0x00000000fef00000 0x00000000ff000000
 G1HR ALLOC(ContinuesH) 0x00000000ff000000 0x00000000ff100000
 G1HR ALLOC(ContinuesH) 0x00000000ff100000 0x00000000ff200000
 G1HR ALLOC(ContinuesH) 0x00000000ff200000 0x00000000ff200010
[GC pause (G1 Humongous Allocation) (young) (initial-mark) G1HR RETIRE 0x00000000fff00000 0x00000000fffd0ec0
 G1HR #StartGC 1 GC回收周期事件
 G1HR CSET 0x00000000fff00000 这个Region是Collection Set
 G1HR ALLOC(Survivor) 0x00000000ffe00000
 G1HR RETIRE 0x00000000ffe00000 0x00000000ffeaa020 回收从0x00000000ffe00000到0x00000000ffeaa020空间
 G1HR #EndGC 1 GC的开始和结束,StartGC 1和EndGC 1标示第一次GC
, 0.0020686 secs]
    [Parallel Time: 1.6 ms, GC Workers: 8]
        [GC Worker Start (ms): Min: 205.6, Avg: 205.8, Max: 206.1, Diff: 0.4]
        [Ext Root Scanning (ms): Min: 0.0, Avg: 1.0, Max: 1.5, Diff: 1.5, Sum: 8.1]
        [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
            [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
        [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
        [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
        [Object Copy (ms): Min: 0.0, Avg: 0.2, Max: 0.9, Diff: 0.9, Sum: 1.9]
        [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.5]
            [Termination Attempts: Min: 1, Avg: 2.3, Max: 4, Diff: 3, Sum: 18]
        [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.3]
        [GC Worker Total (ms): Min: 1.1, Avg: 1.4, Max: 1.6, Diff: 0.5, Sum: 10.9]
        [GC Worker End (ms): Min: 207.2, Avg: 207.2, Max: 207.3, Diff: 0.1]
    [Code Root Fixup: 0.0 ms]
    [Code Root Purge: 0.0 ms]
    [Clear CT: 0.1 ms]
    [Other: 0.4 ms]
        [Choose CSet: 0.0 ms]
        [Ref Proc: 0.2 ms]
        [Ref Enq: 0.0 ms]
        [Redirty Cards: 0.1 ms]
        [Humongous Register: 0.0 ms]
        [Humongous Reclaim: 0.0 ms]
        [Free CSet: 0.0 ms]
    [Eden: 1024.0K(10.0M)->0.0B(9216.0K) Survivors: 0.0B->1024.0K Heap: 6979.7K(20.0M)->6824.0K(20.0M)]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC concurrent-root-region-scan-start]
 G1HR ALLOC(StartsH) 0x00000000ff300000 0x00000000ff400000
 G1HR ALLOC(ContinuesH) 0x00000000ff400000 0x00000000ff500000
 G1HR ALLOC(ContinuesH) 0x00000000ff500000 0x00000000ff600000
 G1HR ALLOC(ContinuesH) 0x00000000ff600000 0x00000000ff700000
 G1HR ALLOC(ContinuesH) 0x00000000ff700000 0x00000000ff700010
[GC concurrent-root-region-scan-end, 0.0008214 secs]
[GC concurrent-mark-start]
[GC concurrent-mark-end, 0.0000931 secs]
[GC remark [Finalize Marking, 0.0052289 secs] [GC ref-proc, 0.0000937 secs] [Unloading, 0.0006454 secs], 0.0062045 secs]
 [Times: user=0.03 sys=0.00, real=0.01 secs] 
 G1HR ALLOC(Eden) 0x00000000fff00000
[GC cleanup 10M->10M(20M), 0.0002773 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 garbage-first heap total 20480K, used 10920K [0x00000000fec00000, 0x00000000fed000a0, 0x0000000100000000)
   region size 1024K, 2 young (2048K), 1 survivors (1024K)
 Metaspace used 2657K, capacity 4486K, committed 4864K, reserved 1056768K
   class space used 288K, capacity 386K, committed 512K, reserved 1048576K

原文地址:https://www.cnblogs.com/lujiango/p/9021279.html