G1回收器(一)

G1的概念

G1是一个并行与并发回收器,他把堆内存分割为很多不相关的区域(Region)(物理上不连续),就是在延迟可控的情况下,获得尽可能高的吞吐量,在两者之间尽量保证平衡,其担当起全功能收集器的重任和期望;

  1. 虽然分成了许多不同的区域(Region),但是仍然延用了分代算法,保留了新生代和老年代的概念;

  2. Region和Region之间使用复制算法进行垃圾回收,从整理的宏观角度使用是标记-整理算法进行回收;

  3. 关注低延时(这一点与CMS类似),达到可预测的停顿,能够支持指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间大概率不超过N毫秒这样的目标;自己理解为通过增量收集算法实现,将内存分为多个区域,在单位时间内,尽可能的收集一块回收率高的区域;

先看下G1示意图,加深下印象,大概长这样子:

在这里插入图片描述

概念补充

在这里插入图片描述

1.本地分配缓存(LAB)

每个应用线程和GC线程都会独立的使用分区,进而减少同步时间,提升GC效率,这个分区称为本地分配缓冲区(Lab)

2.线程本地分配内存(TLAB)

应用线程可以独占一个本地缓冲区(TLAB)来创建的对象,而大部分都会落入Eden区域(巨型对象或分配失败除外),因此TLAB的分区属于Eden空间;

3.晋升本地缓冲区PLAB

GC独占的本地缓冲区进行操作,该部分称为晋升本地缓冲区(PLAB)

4.GC线程本地缓冲区(GCLAB)

每次垃圾收集时,每个GC线程同样可以独占一个本地缓冲区(GCLAB)用来转移对象,每次回收会将对象复制到Suvivor空间或老年代空间;

5.point-into

表示谁引用了我,remembered set就是此实现

6.point-out

表示指向别人的关系,card table基于此思想实现

7.Per Region Table

由于RSet的记录要占用分区的空间,如果一个分区非常"受欢迎",那么RSet占用的空间会上升,从而降低分区的可用空间。G1应对这个问题采用了改变RSet的密度的方式,在PRT中将会以三种模式记录引用:

1.稀少:直接记录引用对象的卡片索引

2.细粒度:记录引用对象的分区索引

3.粗粒度:只记录引用情况,每个分区对应一个比特位

8.SATB

SATB (Snapshot At The Beginning,初始快照),是一种将并发标记阶段开始时对象间的引用关系,以逻辑快照的形式进行保存的手段;

简单理解就是,在并发标记时,以当前的引用关系作为基础引用数据,不考虑Mutator并发运行时对引用关系的修改(Snapshot命名的由来),标记时是存活状态就认为是存活状态,同时利用SATB Write Barrier记录引用变化。

要理解G1回收器,记忆集,卡表和写屏障的概念是必须要知道的,加油吧

记忆集和卡表

关于记忆集和卡表的基本概念自己这里只简单概述,详细描述可以看周志明老师的深入理解jvm虚拟机第三版的3.4节

记忆集(Remember Set):为解决对象跨代引用所带来的问题,垃圾收集器在新生代中建立了名为记忆集(Remembered Set)的数据结构,用以避免把整个老年代加进GC Roots扫描范围

卡表(Card Table):记忆集是一种抽象的数据结构,卡表是记忆集的一种实现;

书中有一段这样的描述:
在这里插入图片描述

也就是说:

遍历Card Table的话,如果table[index] = 1, 那么就可以通过**“起始地址 + index * 卡页的基本单位(512K)”**来得到脏页对应的需要加入到GCRoots的对象空间;
在这里插入图片描述

如上图,老年代中对象y引用了新生代中的对象x,此时Edan区内存满了触发minor gc,此时除了局部变量表/静态属性等要加入GCRoots以外,老年代对象y也应当加入GCRoots;此时我们通过遍历card table数组,发现下标为1对应的page为脏页,那么我们如果通过**“老年代内存起始地址 + 下标 * 卡页的基本单位(512K)”**就可以直接将cardpage2中所有的对象加入到GCRoots,以此避免将整个老年代加入到GCRoots;此基于card table实现的我指向了谁的关系,是point-out的一种实现(见上);

G1中的Rset和Card Table

G1 垃圾收集器将堆内存划分为若干个 Region,每个 Region 分区只能是一种角色,Eden区、Survivor区、Old区老年代的其中一个,同时维护了一个全局的卡表来记录所有的脏页;每个Region的大小在1M到32M之间,Region的数量设置为2的指数倍,默认为2048;

同时按照卡表(card table)的思想逻辑上划分为固定大小(512字节)的连续区域,每个区域称之为卡片 card,因此 card 是堆内存中的最小可用粒度,分配的对象会占用物理上连续的若干个card,当查找对分区内对象的引用时便可通过卡片 card 来查找(见RSet);

*若我们知道堆内存的起始地址,那么 对象的内存地址 = 堆内存起始地址 + (card page index) 512B **

反之 cardpage在card table中的index应为,card page index = (对象的内存地址 - 堆内存起始地址)/ 512B

每个Region都维护了各自的Remember Set来记录其他Region引用了当前Region内对象的对象地址,将各自过程中出现的跨区域引用关系通过key-value的方式记录下来;
在这里插入图片描述

如果region 2中对象b引用了region 1中的对象a,那么region1中的RSet中应该记录上的是key = region2的起始地址,value应该为对应的card table的下标999;

在这里插入图片描述

注意:G1中并不是所有的引用关系都会记录RSet,实际上只会记录Old区到S区或者Old区到E区的引用;并且不重复添加dirty card

写屏障

既然有了通过RSet来避免扫描整个Old区,那么具体是如何维护的Rset呢?

java中存在写屏障这种概念,写屏障相当于Aop切面的概念,也就是说赋值的前后执行自己预先设定的代码

需要注意的是,按照课程中的讲解,存在赋值的时候,只是保存对象的引用信息到一个Darty Card Queue中,到年轻代垃圾回收的时候才从改队列中取出进行处理来更新卡表;这样就不用在每次复制操作的时候去更新卡表了;

举例来说,每一次将一个老年代对象的引用修改为指向年轻代对象,都会被写屏障捕获,并且记录下来。因此在年轻代回收的时候,就可以避免扫描整个老年代来查找根。

那么加入存在y.obj = x ,y和x处于不同的Region,那么执行赋值代码时流程大致如下:

  1. 检查引用和被引用新对象是否在同一个区域,是否是老年代对新生代的引用

  2. 是否重复添加dirty_card

  3. 将y的所在card page地址添加到x所在region的RSet中

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
G1(Garbage First)垃圾回收是一种低延迟的垃圾回收,它可以在不影响应用程序吞吐量的情况下,有效地处理大量的内存垃圾。下面是G1垃圾回收的执行流程: 1. 初始标记(Initial Mark):该阶段的目标是标记所有的根对象,并且标记从根对象直接可达的对象。为了达到这个目的,G1垃圾回收会扫描所有的Java线程的栈,以及记录下所有的GC Root。 2. 并发标记(Concurrent Mark):在初始标记之后,G1垃圾回收会开始并发的标记所有从根对象可达的对象。这是一个并发的过程,不会阻塞应用程序的执行。 3. 最终标记(Final Mark):在并发标记之后,G1垃圾回收会再次暂停应用程序的执行,以完成所有未被标记的存活对象的标记。这个过程与初始标记是类似的。 4. 筛选回收(Live Data Counting and Evacuation):在最终标记之后,G1垃圾回收会计算每个区域中存活的数据量。然后,它会选定一些区域作为回收集(Collection Set),将这些区域中的存活对象复制到空闲的区域中,并将这些区域标记为可回收的。 5. 清除(Cleanup):在筛选回收之后,G1垃圾回收会开始清理所有被标记为可回收的区域。 需要注意的是,G1垃圾回收是一个全局垃圾回收,因此它不仅仅会处理单个堆区域的垃圾回收,而是会处理整个Java堆。同时,它还会根据应用程序运行的情况,动态地调整回收集的大小,以达到最佳的垃圾回收效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@晴天_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值