1 概述
- 关注最小暂停时间,定义一个暂停时间,不要求每次清理都要清理干净。-XX:MaxGCPauseMilis=10,不超过10ms。
- 弱化了分代的概念,使用region的概念,可以更好的控制碎片问题。
1.1 为什么叫G1?
G1的全称是GarbageFirst GC,G1把堆切成了很多份,把每一份当作一个小目标,每一份收集时间自然是很好控制的。那么题又来了:G1有年轻代和老年代区分吗? G1有小堆区和大堆区,每个大小是2的次数大小(0~32M),在内存上是不连续的。
1.2 GC模式
yong gc
mixed gc 该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region。 这里是一部分,主要是因为可以选择哪些old region来进行回收,从而在时间上可以更好的控制。
full gc 如果老年代被填满,就会触发full gc,完全是单线程去处理,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full gc.
2 详解1
HotSpot技术团队一直是朝着高效率收集、减少停顿的方向去努力的。
CMS的缺点:
1 垃圾收集时间不可控:CMS回收失败时,将触发担保机制(Concurrent model fail),串行老年代收集器将会以STW的方式进行一次GC,从而造成较大停顿时间;
2 老年代采用标记清除算法,会产生空间碎片。
G1的内存模型
卡片Card
在每个分区内部又被分成了若干个大小为512 Byte卡片(Card),标识堆内存最小可用粒度。所有分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片。
- 当查找对分区内对象的引用时便可通过记录卡片来查找该引用对象(见RSet)。
- 每次对内存的回收,都是对指定分区的卡片进行处理。
分代收集
年轻代内存会在初始空间-XX:G1NewSizePercent(默认整堆5%)与最大空间(默认60%)之间动态变化。
且由参数目标暂停时间-XX:MaxGCPauseMillis(默认200ms)、需要扩缩容的大小以-XX:G1MaxNewSizePercent及分区的已记忆集合(RSet)计算得到。
将关注点放在最近分配的对象上,而无需整堆扫描,减少长命对象的拷贝。逻辑上划分为年轻代和老年代, 其中年轻代又划分为Eden空间和Survivor空间。但年轻代并不是固定不变的,当年轻代满的时候,会分配空闲列表里的region给年轻代,年轻代整体大小也是可以种植的。
本地分配缓存
每个应用线程和GC线程都会独立的使用分区,进而减少同步时间,提升GC效率,这个分区称为本地分配缓冲区(Lab)。
2 详解2
每个分区都可能是年轻代或者老年代,只是某一时刻只能属于其中一个。 它相对于CMS,最重要的优点在于: 1) 在物理上没有连续,可以花费较少的时间来收集垃圾,因为它优先收集垃圾较多的区域。 2) 带压缩的收集器,在回收老年代时,是将存活的对象从一个区拷贝到另一个区,这个过程就实现了空间整理。
2.1 巨型对象
一个对象大于分区的一半大小,接在老年代分配,所占用的连续空间称为巨型分区(Humongous Region)。G1内部做了一个优化,一旦发现没有引用指向巨型对象,则可直接在年轻代收集周期中被回收。
2.2 RSet已记忆集合
为了减少每一次确定垃圾对象的STW的过程,每个分区维护了一个集合,用来指向别的分区卡片内的对象的(引用了本分区的对象),同时,也可以确定哪个分区的垃圾最多。
这个Rset其实是一个hash table,key是别的region的起始地址,value是一个集合,里面的元素是card table的index。
2.3 CSet可收集集合
在每次GC暂停时,CSet都会被清空,存活的对象被转移了。 G1的收集都是根据CSet进行操作的,年轻代收集与混合收集没有明显的不同,最大的区别在于两种收集的触发条件。 年轻代收集集合CSet 当eden区满的时候,将存活的对象转移到surivior中或者老年代中,原有的区域将会被清空。 混合收集集合 CSet of Mixed Collection 当老年代占用空间超过整堆比IHOP阈值,G1就会启动一次混合垃圾收集周期。 为了满足暂停目标,G1可能不一口气将所有的候选分区收集掉,因此G1可能会产生连续多次的混合收集与应用线程交替执行,每次STW的混合收集与年轻代收集过程相类似。