G1 垃圾回收器

 引用:

  1. G1垃圾收集器详解_fyygree的博客-CSDN博客

  2. 深入解析G1垃圾收集器与性能优化_铁锚的博客-CSDN博客

  3. 垃圾回收器之 G1 垃圾回收器_嘿,鱼骨头^O^的博客-CSDN博客

G1是一款增量式的分代垃圾收集器

G1 物理上不分代,默认会将整个内存区域分为2048个region,region的大小为1MB-32MB,且为2的N次幂。适合内存大的jvm。 region可分为四种类型,且region并不是固定的,运行时会改变

  • Eden Space 新生代

  • Survivor Space 存活区

  • Old Generation 老年代

  • humongous 存储大对象,如果超过0.5个region,就放入humongous

    对于堆中的大对象,默认直接会被分配到老年代,但是如果它是一个短期存在的大对象, 就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区, 它用来专门存放大对象。如果一个H区装不下一个大对象,那么G1会寻找连续的H区来 存储。为了能找到连续的H区,有时候不得不启动Full GC。 G1的大多数行为都把H区 作为老年代的一部分来看待。

    img

G1尽可能多的从有空闲的region中回收内存,同时到达预期的暂停时间指标。

card table (卡表)

在这里插入图片描述

老年代的每个region是有card组成的, 每个card 的大小是大约是512k。如果老年代的对象引用了新生代的对象,我们就把这个card标记为脏card,这样根据GC roots 找对象的时候就不用遍历整个老年代了,只在脏card中寻找就可以了。减少扫描范围,提升效率

RememberSet(记忆集)

在这里插入图片描述

新生代中每个region中都有个RememberSet(记忆集),简称Rset,用来记录哪个card指向这个region的引用。通过这种数据结构,G1就可以进行增量式回收内存,而不用扫描整个堆内存,因为只要扫描Rset,就可以知道哪些跨区的引用指向这个Region,从而对这些region进行回收。

G1的垃圾回收模式

  • young GC:只回收新生代

    会收集eden区和上一次gc使用的存活区,采用复制的方式转移到新的Region中,如果达到分代年龄或者其他条件,会转移到老年代中

    默认老年代占用到整个堆空间的大约45%时,它就会进行这个并发标记

  • mixedGC:回收一部分新生代和老年代

    当老年代的内存超过一个阈值。并发标记完毕之后,会从 young GC模式切换到mixed GC,除了回收eden区和上一次gc使用的存活区,还会选择一部分的老年代进行回收。在进行老年代回收时依然采用复制算法,因为复制算法执行的快。经过多次混合模式的垃圾回收,很多老年代的region已经被处理过了,就会切换到young GC

    tips:

    如果你的回收速度是高于新的用户线程产生的垃圾的速度的时候,也就是我的回收速度比你新产生的垃圾快,来得及打扫,这个时候还不叫 Full GC,这个时候还是处于并发垃圾收集的阶段,虽然重新标记和数据拷贝的过程还会有暂停,但是这个暂停时间还是相对很短的,这还称不上 Full GC,那 G1在什么时候才会发生 Full GC呢,就是当你的垃圾回收的速度跟不上垃圾产生的速度了,新产生的垃圾比你的回收速度快了,这个时候并发收集就失败了,就跟以前的 CMS 类似,这时候它就会退化一个串行的收集,串行收集这时候就会叫Full GC了,特别的慢,当然也会更长时间的 STW 导致响应时间变长。

标记的各个阶段

  • 初始标记。stw,扫描GC roots

  • 并发标记。根据GC roots扫描整个堆,找到存活的对象

  • 重新标记。stw,通过写屏障+SATB(原始对象快照)的方式标记对象

    它是在pre-write barrier写屏障技术在对象引用改 变前把这个对象加入到了一个队列,并且表示它是未被处理的,这个队列的名称叫 satb_mark_queue,将来的 Remark 阶段就可以配合这个队列来对这些对象进行进一步的判断,

  • 并发清楚。

G1垃圾收集器的运行过程:

①. G1 GC的垃圾回收过程主要包括如下三个环节:

  • 年轻代GC (Young GC)

  • 老年代并发标记过程 (Concurrent Marking)

  • 混合回收(Mixed GC)

(如果需要,单线程、独占式、高强度的Full GC还是继续存在的。它 针对GC的评估失败提供了-种失败保护机制,即强力回收。)

img

顺时针young gc -> young gc + concurrent mark-> Mixed GC顺序,进行垃圾回收

②. 应用程序分配内存,当年轻代的Eden区用尽时开始年轻代回收过程;*G1的年轻代收集阶段是一个*并行(多个垃圾线程)的独占式收集器。在年轻代回收期,G1 GC暂停所有应用程序线程,启动多线程执行年轻代回收。然后从年轻代区间移动存活对象到Survivor区间或者老年区间,也有可能是两个区间都会涉及

③. 当堆内存使用达到一定值(默认45%)时,开始老年代并发标记过程

④. 标记完成马上开始混合回收过程。对于一个混合回收期,G1 GC从老年区间移动存活对象到空闲区间,这些空闲区间也就成为了老年代的一部分。和年轻代不同,老年代的G1回收器和其他GC不同,G1的老年代回收器不需要整个老年代被回收,一次只需要扫描/回收一小部分老年代的Region就可以了。同时,这个老年代Region是和年轻代一起被回收的。

⑤. 举个例子:一个Web服务器,Java进程最大堆内存为4G,每分钟响应1500个请求,每45秒钟会新分配大约2G的内存。G1会每45秒钟进行一次年轻代回收,每31个小时整个堆的使用率会达到45%,会开始老年代并发标记过程,标记完成后开始四到五次的混合回收

G1的可选过程:Full GC

  • G1的初衷就是要避免Fu1l GC的出现。但是如果上述方式不能正常工作,G1会停止应用程序的执行(Stop-The-World) ,使用单线程的内存回收算法进行垃圾回收,性能会非常差,应用程序停顿时间会很长。

  • 要避免Full GC的发生,一旦发生需要进行调整。什么时候会发生Full GC呢? 比如堆内存太小当G1在复制存活对象的时候没有空的内存分段可用,则会回退到full gc, 这种情况可以通过增大内存解决。

  • 导致G1Full GC的原因可能有两个: .

    1. 回收的时候没有足够的to-space来存放晋升的对象

    2.并发处理过程没完成空间就耗尽了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值