JVM窥探——G1收集器

在这篇博客《JVM(2)——GC算法和收集器》中,简单介绍了GC的算法和收集器。今天主要介绍其中的一种收集器G1。

一、目标

尽最大可能减少STW时间;
GC停顿可控;
不产生内存碎片和浮动垃圾。

二、特点

1、化整为零,引入region。

Region

Java堆划分成多个独立区域Region,新生代和老年代也不再是物理隔离的,他们都是一部分Region集合。新增的Humongous区,专门用来存放临时的大对象。如下图:
在这里插入图片描述

RSet

Remembered Set,每个Region初始化时都会有一个RSet,类似一个Hash Table,记录了哪些Region对当前Region的引用【key:Region的起始地址 value:Card Table的index】。在进行后续标记的过程中,RSet也会做同步修改。

用空间换时间,以避免对全堆扫描。

Card Table

也叫卡表,通常是字节数组,卡表中的每个区域叫卡。由Card的索引数组下标来标识每个分区的空间地址。用来标记是否被引用,0-未被引用 1-被引用。
在这里插入图片描述

2、多种收集算法

分代收集,整体上“标记-整理”,局部是“复制”。

设计思路:面向局部收集

分代收集:不需要和其他收集器配合就能独立管理整个GC堆,分代能达到更好的收集效果。

空间整合,避免内存碎片。

G1的垃圾回收模式有两种:Young GC 和Mixed GC(混合回收)。

Young GC

该模式下,主要处理Eden->Survivor,Survivor->Old,Eden->Old等。和之前提到的年轻代GC算法没有太大区别,该阶段主要使用了复制等算法。

Mixed GC:

主要针对年轻代和部分老年代区域进行回收。

步骤作用是否需要STW
初始标记标记GC Root直接关联的对象
并发标记从GC Root做可达性分析,重新处理STAB记录下的并发时有引用修改的对象
最终标记处理并发标记结束后仍遗留的SATB记录
筛选回收回收效率计算;并进行GC

下图为初始标记示意图:
在这里插入图片描述

  • 哪些可以作为GC Root直接关联的对象?
    静态变量(上图左下角方法区中所示),方法的局部变量(可以理解成上图右侧GC回收线程开始的GC Root)。

  • STW(停顿)如何体现?
    上图左侧的系统线程处于“禁止运行”状态。

  • G1的并行与并发如何体现?
    并行:充分利用多核CPU资源。
    并发:第二个步骤并发标记,在该阶段,垃圾回收线程和用户程序(上图左上角系统线程)并发执行。且由于是并发处理,可能会出现标记产生变动。

  • 并发标记阶段,如何区分哪些对象被访问过?
    G1采用原始快照SATB(Snapshot At The Beginning)来实现,在GC开始时,对活着的对象进行一个快照。之后用三种颜色标记对象:白色-未被访问过,黑色-已经被访问过且对象的所有引用也被扫描过了,灰色-已经被访问过,但对象至少有一个引用还没被扫描过。(引用的是白色)

快照三色关系图示:
在这里插入图片描述

GC前GC后是否会被回收
白色白色是-对象不可达
白色黑色否-安全
黑色黑色否-安全
灰色黑色否-安全

3、可预测的停顿

G1追求低停顿,并且建立可预测的停顿时间模型。

(1)如何做?
避免在整个堆中进行全区域的GC。G1维护一个Region的优先列表,按回收价值排序。

回收价值=回收所获得的空间大小/回收所需时间。

在GC时,优先回收价值最大的Region。这样在一定程度上保证了回收的效率。

region回收空间回收所需时间回收价值
RegionA200ms20MB0.1
RegionB1000ms10MB0.01

(2)G1如何拿到各个Region的回收价值?(包括:预计回收空间、回收所需时间等)
G1内部收集每个Region回收耗时,再根据历史数据的偏差、置信度等统计数据,由哪些Region组成的回收集合才能达到期望停顿值之内的最高收益。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值