G1收集器

区域化分代式垃圾回收器




简单介绍G1 GC


官方给G1垃圾收集器设定的目标:

在延迟可控的情况下获得尽可能高的吞吐量,所以才担当起"全功能收集器"的重任与期望

G1是一款面向服务端应用的垃圾收集器,主要针对配备多核CPU及大容量内存的机器,以极高概率满足GC停顿时间的同时,还兼具吞吐量的性能特征。


为什么名字叫做Garbage First 呢?

1.G1是一个并行的回收器,它把堆内存分割为很多不想关的区域(region)(物理上不连续的)使用不同的region来表示Eden,幸存者0区,幸存者1区,老年代等

2.G1 GC有计划的避免在整个java堆进行全区域的垃圾收集,G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的region

3.由于这种方式的侧重点在于回收垃圾最大量的区间(region),所以我们取名为垃圾优先 Garbage First


G1回收器的特点(优点)


并行并发

1.并行性: G1在回收期间,可以有多个GC线程同时工作,有效利用多核计算能力。此时用户线程STW

2.并发性: G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段发生完全阻塞应用程序的情况

分代收集

1.从分代上看,G1依然属于分代型垃圾回收器,它会区分年轻代和老年代,年轻代依然有Eden区和Survivor区。但从堆的结构上看,他不要求整个Eden区,年轻代或者老年代都是连续的,也不再坚持固定大小和固定数量

2.将堆空间分为若干个区域(Region),这些区域中包含了逻辑上的年轻代和老年代

3.和之前的各类回收器不同,它同时兼顾年轻代和老年代。

空间整合

1.G1将内存划分为region,内存的回收以region为单位,region之间是复制算法,但是整体上可看作是标记-压缩算法,这两种算法都可以避免内存碎片,这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。尤其当堆非常大的时候,G1的优势很明显


可预测的时间停顿模型(即:软实时soft real-time)

这是G1相对CMS的另一大优势,G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒

1. 由于分区了,G1可以每次只选取部分区域进行回收,缩小了回收的范围,因此对于全局停顿情况的发生也能得到较好的控制

2.G1跟踪多个region里面的垃圾堆积的价值大小(回收能获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的region,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率 

3.相比CMS GC,G1未必能做到CMS在最好情况下的延时停顿,但是最差情况要好很多

4.为啥叫软实时,因为G1不能确保垃圾回收的停顿时间一定在你的设置时间之内,只能尽量确保,所以是软实时



G1垃圾回收器的缺点


1相较于CMS,G1并没有具备全方位碾压优势,比如在用户程序运行过程中,G1无论是为了垃圾收集产生的内存占用还是程序运行时的额外执行负载都要比CMS要高(G1会有Remembered Set 等额外内存占用,大概是10到20),从经验上来说,在小内存上CMS的表现大概率超过G1,而G1在大内存应用上能发挥它的优势,平衡点在6-8G之间



G1回收器的参数设置


-XX:+UseG1GC    

手动指定使用G1收集器

-XX:G1HeapRegionSize

设置每个Region的大小,值是2的幂,范围是1到32MB,目标是根据最小的java堆大小划分出约2048个区域,默认是堆内存的1/2000

-XX:MaxGCPauseMillis

设置期望达到的最大GC停顿时间指标(JVM会尽力实现,并不保证达到) 默认是200ms

-XX:ParallelGCThread 

设置STW工作线程数的值,最多设置为8

-XX:ConcGCThreads

设置并发标记的线程数,一般设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右

-XX:InitiatingHeapOccupancyPercent

设置触发并发GC周期的Java堆占用率阈值,超过此值,就触发GC,默认45



G1回收器的适用场景


面向服务端应用,针对具有大内存,多处理器的机器。最主要就是需要低延迟,具有大内存堆的应用程序

比如在堆大小约6G或者更大的时候,可预测的停顿时间低于0.5秒(G1通过每次只清理一部分而不是全部region的增量式清理来保证每次GC的停顿时间)

对于打算从CMS或者ParallelOld收集器迁移过来的应用,按照官方 的建议,如果发现符合如下特征,可以考虑更换成G1收集器以追求更佳性能:

1.超过50%的java堆被活动数据占用

2.对象分配频率或者年代提升频率变化很大

3.GC停顿时间过长(长于0.5秒至1秒)

HotSpot垃圾收集器里,除了G1以外,其他的垃圾收集器使用内置的JVM线程执行GC的多线程操作,而G1 GC可以采用应用线程承担后台运行的GC工作,即当JVM的GC线程处理速度慢时,系统会调用应用程序线程帮助加速垃圾回收过程



Region介绍


G1收集器会将整个堆划分为一个个的region 块,所有的region块大小大同,且在JVM生命周期内不会被改变。

虽然还保留了新生代和老年代的概念,但不再是物理隔离的了,都是一部分region(不需要连续)的集合,通过region动态分配方式 实现逻辑上的连续



设置H大对象内存区域的原因

对于大对象,默认一般都是直接分配到老年代了,但是如果它是一个短期存在的大对象,放在老年代,老年代因为回收频率很低,导致它长期存在,类似内存泄漏了,不太好,所以专门划分了一个Humongous区,专门存放大对象,如果一个H区装不下一个大对象,那么G1会寻找连续的H区来存储,为了找到连续的H区,有时候会不得不启动Full GC ,G1的大多数行为都把H区作为老年代的一部分来看待



G1回收器的垃圾回收过程


1.年轻代GC(Young GC)

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

3.混合回收(Mixed GC)

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






记忆集和写屏障


一个对象被不同区域引用的问题

一个region不可能是孤立,可能被其他任意region中的对象所引用,判断对象存活时,是否需要扫描整个Java堆才能保证准确?

其他收集器也有这个问题,G1更突出一点,因为G1针对大堆

难道回收年轻代一定得扫描老年代吗?那还如何保证效率呢?


解决办法

1.无论是G1还是其他分代收集器,JVM都是使用Remembered Set来避免全局扫描

2.每个region都有一个对应的R Set



3.每次引用类型数据写操作时,都会产生一个Write Barrier(写屏障)暂时中断操作,然后检查将要写入的引用指向的对象是否和该引用类型数据在不同的Region(其他收集器也一样,检查老年代对象是否引用了新生代对象),如果不在同一个region,通过CardTable把相关引用信息记录到引用指向对象的所在region对应的R Set中

4.当进行垃圾收集的时候,在GC根节点的枚举范围内加入R Set ,就可以保证不进行全局扫描,也不会遗漏了



G1垃圾回收的具体过程


过程1:年轻代GC



上图有个不准确的地方,Eden区回收之后,就应该变为空闲区域了



针对第二阶段补充说明

对于一个操作 例如 Object.field = Object JVM会在之前和之后进行特殊操作以在dirty card queue中入队一个保存了对象引用信息的card,在年轻代回收的时候,G1会为Dirty Card Queue 中所有的card进行处理,以更新R Set 保证R Set能实时准确的反映引用关系

为什么不在引用赋值的时候直接更新RSet呢,考虑到了性能的问题,RSet的处理需要线程同步,开销很大,使用队列性能好一点


针对第五阶段说明

回收之后,空闲的region 会被一个linkedList管理起来,进行动态分配



过程2:并发标记阶段



另一种说法



过程3:混合回收



过程4:Full GC






G1回收器优化建议






收集器大总结



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容