Garbage First(G1)垃圾收集器

1. 概述

G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器一样,G1也是关注最小时延的垃圾回收器。

G1最大的特点是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。

2. G1

2.1 特点

开启方式:-XX:+UseG1GC

串行、并行、CMS等收集器有如下共同点:

(1)年轻代、老年代是独立且连续的内存块;

(2)年轻代收集使用单Eden、双Survivor进行复制算法;

(3)老年代收集必须扫描整个老年代区域;

(4)都是以尽可能少而快执行GC为设计原则。

G1也有类似CMS的收集动作:初始标记、并发标记、重新标记、清除、转移回收(Region),并且也以一个串行收集器做担保机制。

G1的特点如下:

(1)G1的设计原则是“首先收集尽可能多的垃圾(Garbage First,名称的由来)”。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;

(2)G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);

(3)G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;

(4)G1收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而降低停顿。

2.2 G1内存模型

2.2.1 分区Region

G1采用分区(Region)的思路,将整个堆空间分成若干个大小相等的内存区域,每次分配对象空间将逐段使用内存。因此,在堆的使用上,G1并不要求对象的存储一定是物理上连续的,只要逻辑上连续即可;每个分区也不会确定为某个代(年轻代、老年代)服务,可以按需在年轻代和老年代之间切换。参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,必须是2的幂),默认将整个堆划分为2048个分区。

2.2.2 卡片Card

在每个分区内部被分成了若干个大小为512byte卡片(Card),标识堆内存最小可用粒度所有分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片,当查找对分区内对象的引用时便可通过记录卡片来查找该引用对象。每次对内存的回收,都是对指定分区的卡片进行处理。

2.2.3 堆Heap

G1同样可以通过-Xms、-Xmx指定堆空间大小,当发生年轻代收集或混合收集时,通过计算GC与应用的耗费时间比,自动调整堆空间大小。如果GC频率太高,则通过增加堆尺寸,来减少GC频率,相应地GC占用的时间也随之降低;目标参数-XX:GCTimeRatio即为GC与应用的耗费的时间比,G1默认为9。另外,当空间不足,如对象空间分配或转移失败时,G1会先尝试增加堆空间,如果扩容失败,则发起担保的Full GC。Full GC后,堆尺寸计算结果也会调整堆空间。

猜你喜欢

转载自www.cnblogs.com/lujiango/p/9020503.html
今日推荐