G1垃圾回收器简介

G1垃圾回收器

Garbage first回收器,优先收集垃圾多的区域。之前的垃圾回收器使用的过程中,都是将整个年轻代(survivor区和eden区)进行回收和整个老年代进行回收,G1希望在可配置的限定时间(STW时间)内完成垃圾回收,那么就只能减少回需要回收的区域(region),减少回收的区域可能就需要增大触发YGC的频率。这会降低JVM的吞吐量。G1一般使用在堆内存空间较大的情况下。
在这里插入图片描述

G1垃圾回收器有两种垃圾回收模式

  • Fully Young GC
  • Mixed GC

跨代对象引用

在这里插入图片描述

其实本质就是将一个区分为大小相对的更小的card,如果说一个card中有对象指向别的代中的对象的时候,那么将老年代这个card放入新生代的RS中

在这里插入图片描述

Write Barrier

写栅栏,在G1中,给出一个field对指针操作的改变进行记录,当更新这个指针的时候(这里应该表示的是这个指针的地址值发生改变或者删除的时候)会将这个Card标记为Dirty,然后将Dirty的Card放入到脏卡片队列中(这个指针发生改变后就应该让它所指向的对象所在的Region的RS进行更新因为引用它的对象的指针发生改变了,当进行可达性分析的时候就可能发生空指针异常。),用白/绿/黄/红四种颜色来表示当前队列中脏卡片的数量多少,越往又程度越大。

​ 那么这个Barrier和锁中的Barrier是不一样的,它是在JVM中注入的一段代码,用于记录该指针的变化。多线程问题中的Barrier是内存屏障是保护一个对象在对齐进行读写操作的时候进行隔离而不受更改的。

WriteBarrier是由JVM自动生成的一小段代码来检测对象之间的引用是否被更改,如果被更改则标记Card为Dirty,而不直接到RS中更新,是因为对象之间相互引用的赋值操作是十分经常的,而Java程序都是多线程执行的,如果多线程对RS访问的时候必然会出现需要对RS加锁的情况产生多线程切换的开销,而它只将Dirty Card放入队列中,并且在之后由清理线程再去处理这个队列就能减少多线程之间上下文互相切换的问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D046hnIH-1603787993505)(X:\笔记\截图\image-20201027104817588.png)]

程度不同,则开启更新RS的线程数量也不同,如果达到红色的阈值后,应用现场也会参与到RS的更新中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lsjaGrVW-1603787993507)(X:\笔记\截图\image-20201027105255557.png)]

G1的Fully YoungGC

​ G1的YGC是会STW的(并且其STW的时间是可以配置的(大约能达到10ms)),首先构建CS区(eden+survivor),这些区域是大概率能回收效率较高的区域,之后扫描GC的roots,更新这些区域的RS(将Dirty Card Queue清空)这一步保证了当前的RS状态是最新的了,找到被老年代对象引用的的对象,之后进行对象拷贝(往往这一步是将几个Edern区和Survivor区中未被回收的对象一起放到新的区域中)和引用更新。

在这里插入图片描述
在这里插入图片描述

Old GC

Old GC是在堆中内存达到一定比例的时候就会进行的。

在G1中OldGC是并发执行的,即在进行Old GC的过程中应用进程是不暂停的,采用三色标记算法。BFS
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NcfHoa6d-1603787993511)(X:\笔记\截图\image-20201027160049161.png)]

首先会执行一次YGC,OldGC需要使用到YGC的结果,恢复应用线程后,进行并发的初始标记(三色标记算法),之后STW,进行一次保证安全的Remark,保证我所标记到的对象都是真实存在的对象而不产生空指针异常。

三色标记算法

在这里插入图片描述

在并发标记的时候一开始所有对象都是白色的,找到根节点即GC ROOTS,将GC Roots标记为黑色,并且将他所指向的引用对象标记为灰色,并且放入一个队列中。

之后接着从队列中提取节点,将这些节点标记为黑色并将其指向的对象标记为灰色(BFS),以此类推直到所有的对下那个都被标记为黑色。

​ 因为这个标记过程是并发执行的,应用线程此时也在运作,那么就有可能发生执行顺序不同而产生的错误,在G1中还是采用Write Barrier解决。

也是像前面一样在JVM字节码中添加一小段代码来检测对象之间的相互引用, 虽然执行了B.c = null 的操作但是我们认为c还是一个活的对象,这种操作被称为SATB(在开始前的快照),记录了在GC并发标记的时候的每个对象的初始状态,在并发完成过后,会有Remark阶段处理这种浮动垃圾。

最后进行Cleanup清理的时候仅仅是清空完全都是垃圾的区。

Mixed GC

​ 在老年代回收中,仅仅是将完全都是垃圾的区域进行回收,但是,如果有一个区域中,一半是垃圾一半不是,那么就会浪费空间,而为了解决这种问题,肯定会要有压紧(compact)的操作,肯定会产生内存直接拿的相互copy,在CMS中只有内存的清理工作,而没有内存压缩操作就很容易产生内存碎片。

在这里插入图片描述

Mixed GC不一定是立即发生的,会选择老年代中的若干个区域进行压缩,默认是1/8,但是是可配置的,因为老年代区和新生代区的Region的大小结构是相同的,那么在压缩的时候会采用相同的算法进行压缩(内存的赋值和拷贝)。

​ 这里还有一个点是G1垃圾回收器是Garbage First,在进行垃圾回收的时候默认是优先拷贝垃圾数据较多的区域,内存赋值拷贝的算法是和一个区域中存活对象多少有关的,存活的对象多那么拷贝量就大,STW的时间就长。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值