Object o = obj.FieldA // 从堆中读取引用,需要加入屏障 <Load barrier> Object p = o // 无需加入屏障,因为不是从堆中读取引用 o.dosomething() // 无需加入屏障,因为不是从堆中读取引用 int i = obj.FieldB //无需加入屏障,因为不是对象引用
与 CMS 中 Young GC 类似,采用标记-复制算法。但是对该算法进行了改进,在标记、转移和重新标记阶段几乎都是并发的。
主要分为以下几个阶段:
并发标记(初始标记、并发标记、再标记):标记阶段会更新指针中 M0,M1 标志位
并发预备重分配(并发转移准备):需要根据条件统计出本次收集清理的 Region,扫描所有 Region
每次会扫描所有的 Region,用范围更大的扫描成本换取 G1 的 Remeber Set 维护成本。G1 为了收益优先做增量回收,需要用 Remember Set 来记录 Region 之间的对象引用关系。但是 RS 占用内存较大。
并发重分配(初始化转移,并发转移):需要将存活对象复制到新 Region,并未重新发配的每一个 Region 维护一个转发表。当用户线程此时访问转发表中的对象时,会被内存屏障拦截,根据转发表转发到复制的新对象上,并更新该引用的值。复制完毕时,该 Region 会立即释放用于分配新对象,但是转发表不会清除用于自愈。
{G1 的转移阶段是完全 STW,且暂停时间与活跃对象的大小成正比。但 G1 支持部分 Region 回收,G1 在写引用时,GC 移动对象需要同步更新 RS。}
2020-09-02T17:22:56.890-0800: 74.347: [GC (Allocation Failure) 2020-09-02T17:22:56.890-0800: 74.347: [ParNew: 734545K->47735K(766784K), 0.0226810 secs] 786003K->103230K(4008768K), 0.0228692 secs] [Times: user=0.12 sys=0.01, real=0.02 secs] 2020-09-02T17:24:36.037-0800: 173.492: [GC (Allocation Failure) 2020-09-02T17:24:36.037-0800: 173.492: [ParNew: 727450K->37114K(766784K), 0.0650905 secs] 799141K->109325K(4008768K), 0.0654584 secs] [Times: user=0.29 sys=0.01, real=0.07 secs] 2020-09-02T17:24:36.103-0800: 173.558: Total time for which application threads were stopped: 0.0703294 seconds, Stopping threads took: 0.0007604 seconds 2020-09-02T17:24:36.130-0800: 173.584: Total time for which application threads were stopped: 0.0045084 seconds, Stopping threads took: 0.0010931 seconds 2020-09-02T17:24:40.141-0800: 177.596: Total time for which application threads were stopped: 0.0041642 seconds, Stopping threads took: 0.0009028 seconds 2020-09-02T17:24:42.955-0800: 180.409: [GC (Allocation Failure) 2020-09-02T17:24:42.955-0800: 180.409: [ParNew: 718714K->35437K(766784K), 0.0185378 secs] 790925K->107647K(4008768K), 0.0186691 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] 2020-09-02T17:24:42.974-0800: 180.428: Total time for which application threads were stopped: 0.0199768 seconds, Stopping threads took: 0.0002223 seconds 2020-09-02T17:24:42.980-0800: 180.435: Total time for which application threads were stopped: 0.0014026 seconds, Stopping threads took: 0.0002243 seconds 2020-09-02T17:24:45.985-0800: 183.439: Total time for which application threads were stopped: 0.0038208 seconds, Stopping threads took: 0.0006331 seconds 2020-09-02T17:24:48.474-0800: 185.929: Total time for which application threads were stopped: 0.0011093 seconds, Stopping threads took: 0.0001436 seconds 2020-09-02T17:24:51.073-0800: 188.528: [GC (Allocation Failure) 2020-09-02T17:24:51.074-0800: 188.528: [ParNew: 717037K->38672K(766784K), 0.0688267 secs] 789247K->110882K(4008768K), 0.0691844 secs] [Times: user=0.34 sys=0.01, real=0.07 secs] 2020-09-02T17:24:51.143-0800: 188.597: Total time for which application threads were stopped: 0.0737748 seconds, Stopping threads took: 0.0006621 seconds 2020-09-02T17:24:51.163-0800: 188.617: Total time for which application threads were stopped: 0.0066130 seconds, Stopping threads took: 0.0018507 seconds 2020-09-02T17:24:53.072-0800: 190.526: Total time for which application threads were stopped: 0.0010838 seconds, Stopping threads took: 0.0001050 seconds 2020-09-02T17:24:53.073-0800: 190.528: Total time for which application threads were stopped: 0.0013641 seconds, Stopping threads took: 0.0000755 seconds 2020-09-02T17:24:54.079-0800: 191.534: Total time for which application threads were stopped: 0.0052378 seconds, Stopping threads took: 0.0005817 seconds 2020-09-02T17:24:56.240-0800: 193.694: Total time for which application threads were stopped: 0.0042420 seconds, Stopping threads took: 0.0004183 seconds 2020-09-02T17:24:58.141-0800: 195.595: [GC (Allocation Failure) 2020-09-02T17:24:58.141-0800: 195.595: [ParNew: 720272K->38427K(766784K), 0.0173455 secs] 792482K->110637K(4008768K), 0.0174675 secs] [Times: user=0.07 sys=0.00, real=0.01