【Java】G1 GC

简介

Garbage First Collector是一款以降低最大暂停时间为目标的服务端回收器。

region

都知道cms使用标记清除算法,会导致内存碎片。g1就是用了划分region的方案来解决内存碎片。g1中,逻辑上可以认为整块内存仍是分代的。物理上,内存被划分为若干等大region。每一块region都可以被用作老年代或者年轻代。

card

每一个region又分为若干card,每一个card对应region内一个块区域。所有的card都会有状态,比方说dirty等,最终都会由统一的全局的card table记录。每一块card都对应card table里的一个entry,每一个entry实现为一个byte字节。

rSet

后面会介绍g1的回收模式。总体而言,g1的回收过程和标记过程是独立的。并且回收是以region为单位进行,为了保证region回收的独立性,每一个region都需要使用rSet记录外部引用,这样在回收时就不需要遍历整堆而只需要遍历rSet就可以完成回收。下面是一个例子:

比方说regionA的一块card被regionB和regionC引用了,那么regionA的rSet就会记录B和C的card。

rSet和上面的carTable都会被写入屏障来修改。

写入屏障

g1的写入屏障技术是一种基于快照的策略,即拦截删除灰色对象的白色引用。为了降低对赋值器的影响,每一次只会生成一个log,然后由专门的线程来处理log,即记录dirtycard或者rSet。这是维护card entry和rSet的策略。

cSet

回收阶段决定的要回收的region集合

bitMap

一般算法比如cms标记对象都是通过设置对象头部的标记位来实现,g1使用了另一种方案,即bitMap。每一个region都有一个bitMap,一个bit对应若干byte的内存区域。标记时,若一个对象是存活的,则将其所在的bit位置为已标记。由于标记和回收可能并行,实际上有两个bitMap,一个是上一次标记的结果pre,可以在回收阶段被使用,另一个用于存放此次标记的结果cur,如果此次标记和回收并行,那么此次标记使用cur,回收使用pre,互不干扰。

tams

top-at-mark-start
用于标记对象分配的起始位置的指针。也有两个。整个region的划分如下:
top是当前分配指针,下一个可分配的位置
next是此次标记时分配对象的起始地址
pre是上一次标记时分配对象的其实地址
[next-top]:此次标记期间新分配的对象
[pre-next]:上一次标记期间分配的对象

模式

回收总共有三种:
ygc,cset只有年轻代,当年轻代满了会触发;
mixed gc,cset除了年轻代,还会包含部分老年代的region,这是根据上一次标记得到的统计信息来决定的,垃圾越多的region越有可能被回收,所以garbage first名字由此而来,优先回收收益最大的regoin。当老年代达到一定阈值会触发多次mixed gc,不是一次就可以收集完的。gc前一定会先触发标记过程。
如果mixed gc无法及时清除完垃圾导致老年代满了,就会触发full gc。

标记过程

1)初始标记:stw,扫描根,标记根直接可达对象,初始标记阶段会在上一次ygc中完成
2)并发标记:非stw,从根直接可达对象扫描其他对象,期间通过写入屏障记录SATB write barrier
3)最终标记:stw,重新扫描SATB write barrier,修正bitMap
4)清理阶段:stw,其实该阶段并不会真正清除,只是根据bitMap统计存活对象数目

 

参考:https://hllvm-group.iteye.com/group/topic/44381

https://www.oracle.com/technetwork/articles/java/g1gc-1984535.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值