JVM学习-G1回收器

15 篇文章 6 订阅

1.简介

定义:
Garbage First

JDK 9以后默认使用,而且替代了CMS 收集器

适用场景
同时注重吞吐量和低延迟(响应时间),默认暂停目标是200ms
超大堆内存(内存大的),会将堆内存划分为多个大小相等的区域
整体上是标记-整理算法,两个区域之间是复制算法
它整体上使用标记整理算法,可以避免CMS垃圾回收器的标记清除算法产生的内存碎片问题
它也属于并发的垃圾回收器

相关JVM参数
-XX:+UseG1GC
-XX:G1HeapRegionSize=size
设置区域大小,区域要设置成1,2,4,8等2的次方数。堆内存大,则会影响回收速度。分成小的区域来进行管理,这样就可以进行优化,加快标记,拷贝的速度。
-XX:MaxGCPauseMillis=time

如果你的jdk是1.8版本,那么就需要用UseG1GC来启动G1垃圾回收器。

2.G1垃圾回收阶段

在这里插入图片描述

新生代伊甸园垃圾回收—–>内存不足,新生代回收+并发标记—–>回收新生代伊甸园、幸存区、老年代内存——>新生代伊甸园垃圾回收(重新开始)

2.1.Young Collection

分区算法region
分代是按对象的生命周期划分,分区则是将堆空间划分连续几个不同小区间,每一个小区间独立回收,可以控制一次回收多少个小区间,方便控制 GC 产生的停顿时间

新生代内存布局如图:
对于G1,它将堆内存划分成大小相等的一个个区域,每个区域都可以独立的作为新生代和老年代。白色的表示空闲的区域,刚开始类加载创建的对象会分配的伊甸园区,图中绿色区域E表示伊甸园区。
在这里插入图片描述
当伊甸园逐渐被占满,就会触发一个stw。伊甸园区的对象就会使用复制算法将其复制到幸存区
在这里插入图片描述
当幸存区的对象比较多,并且幸存区的存活年龄超过一定时间,又会触发新生代的垃圾回收,幸存区的一部分对象又会晋升到老年代,不够年龄的会再次拷贝到另一个幸存区。
在这里插入图片描述

2.2.Young Collection + CM

CM:并发标记
在 Young GC 时会对 GC Root 进行初始标记 不会STW
在老年代占用堆内存的比例达到阈值时,对进行并发标记(不会STW),阈值可以根据用户来进行设定
默认阈值为45%

如图E伊甸园,S是幸存区,O是老年代。当老年代区占用较高时,就开始并发标记。
在这里插入图片描述

2.3.Mixed Collection

会对E S O 进行全面的回收
最终标记
拷贝存活
这两个阶段都会stw
-XX:MaxGCPauseMills:xxx 用于指定最长的停顿时间
问:为什么有的老年代被拷贝了,有的没拷贝?

因为指定了最大停顿时间,如果对所有老年代都进行回收,耗时可能过高。为了保证时间不超过设定的停顿时间,会回收最有价值的老年代(回收后,能够得到更多内存)

混合收集阶段对堆内存进行全面的垃圾回收,伊甸园的幸存对象会被赋值算法复制到幸存区中,幸存区中的符合晋升条件的对象会晋升到老年代中去。还有一部分老年代的区域也经过了并发标记阶段。G1会有选择的将一些老年代区域进行垃圾回收。为什么有的被拷贝了,有的没有呢,因为有时候堆内存空间太大,时间较长,就达不到MaxGCPauseMills。复制一方面是为了保留存活对象,一方面是为了整理内存对象,减少内存碎片。对于老年代来说,在混合阶段,它会优先回收那些垃圾最多的区域,主要目的是为了达到暂停时间最短的目标。
在这里插入图片描述

2.4.FullGC

SerialGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
ParallelGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
CMS
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足
G1
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足

串行和并行的老年代垃圾收集会触发full gc
而CMS和G1内存不足时,会分两种情况。
以G1为例,进行说明
G1老年代内存与整个堆内存占比达到45%时,会触发一个并发标记的阶段,以及后续的混合收集的阶段。这两个阶段工作的过程中,如果回收的速度高于新的用户线程产生垃圾的速度的话,这个时候不叫Full GC,这个时候还是处于并发垃圾收集的阶段,这个时候暂停的时间比较短。当垃圾回收的速度跟不上用户产生垃圾的速度的时候。这个时候并发收集失败,这时候就会退化串行的收集(但是在现在的版本中,G1的Full GC也是多线程的了),叫Full GC。CMS是指并发失败了以后,才叫Full GC,如果并发没有失败,还处于并发收集阶段,它也会出现full gc。

G1在老年代内存不足时(老年代所占内存超过阈值)
如果垃圾产生速度慢于垃圾回收速度,不会触发Full GC,还是并发地进行清理
如果垃圾产生速度快于垃圾回收速度,便会触发Full GC

Full GC 是清理整个堆空间—包括年轻代和永久代

2.5Young Collection 跨代引用

新生代回收的跨代引用(老年代引用新生代)问题
在这里插入图片描述
卡表与Remembered Set

  • Remembered Set 存在于E中,用于保存新生代对象对应的脏卡
  • 脏卡:O被划分为多个区域(一个区域512K),如果该区域引用了新生代对象,则该区域被称为脏卡
    在引用变更时通过post-write barried + dirty card queue

concurrent refinement threads 更新 Remembered Set

2.6.Remark

重新标记阶段

在垃圾回收时,收集器处理对象的过程中

黑色:已被处理,需要保留的 灰色:正在处理中的 白色:还未处理的。最后都处理完成时,因为灰色的有强引用引用它,所以它最终会变成黑色,还是会存活,最下面的一个白色,因为有人引用它,也会存活,也会变成黑色,存活下来,上面的白色因为没有人引用它,所以它会被当成垃圾,进行回收。
在这里插入图片描述
但是在并发标记过程中,有可能A被处理了以后未引用C,但该处理过程还未结束,在处理过程结束之前A引用了C,这时就会用到remark。因为我们用的是并发回收器,在垃圾回收的时候,可能会有其它的用户线程来处理它。

过程如下

  • 之前C未被引用,这时A引用了C,就会给C加一个写屏障,写屏障的指令会被执行,将C放入一个队列当中(如左边的),并将C变为 处理中 状态,表示还未处理完
  • 在并发标记阶段结束以后,重新标记阶段会STW,然后将放在该队列中的对象重新处理,发现有强引用引用它,就会处理它,把它变成黑色,就不会当成垃圾被回收。
    在这里插入图片描述
    参数pre-write barrier+satb_mark_queue
    它是采用pre-write barrier写屏障技术,在对象引用改变前,把对象加入队列,并且表示它是未处理,这个队列叫做satb_mark_queue,将来remark阶段就会对这个队列进一步的判断

3.G1垃圾回收器的优化

3.1.JDK 8u20 字符串去重

优点:节省大量内存
缺点:略微多占用了 cpu 时间,新生代回收时间略微增加
-XX:+UseStringDeduplication

String s1 = new String("hello"); // char[]{'h','e','l','l','o'} 
String s2 = new String("hello"); // char[]{'h','e','l','l','o'}

将所有新分配的字符串放入一个队列
当新生代回收时,G1并发检查是否有字符串重复
如果它们值一样,让它们引用同一个 char[]
注意,与 String.intern() 不一样

  • String.intern() 关注的是字符串对象
  • 而字符串去重关注的是 char[]
  • 在 JVM 内部,使用了不同的字符串表

3.2.JDK 8u40 并发标记类卸载

所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸 载它所加载的所有类 -XX:+ClassUnloadingWithConcurrentMark 默认启用

3.3. JDK 8u60 回收巨型对象

一个对象大于 region 的一半时,称之为巨型对象
G1 不会对巨型对象进行拷贝
回收时被优先考虑
G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生 代垃圾回收时处理掉
在这里插入图片描述

3.4.JDK 9 并发标记起始时间的调整

并发标记必须在堆空间占满前完成,否则退化为 FullGC
JDK 9 之前需要使用 -XX:InitiatingHeapOccupancyPercent
JDK 9 可以动态调整 -XX:InitiatingHeapOccupancyPercent 用来设置初始值
进行数据采样并动态调整 总会添加一个安全的空档空间

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值