G1和CMS

CMS: concurrent Mark Sweep

以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”实现
有人会好奇为什么标记清理算法会产生内存碎片!但是CMS仍采用这种算法呢?

答案是:因为CMS作为第一款实现用户线程和收集线程并发执行的收集器!当时的设计理念是减少停顿时间,最好是能并发执行!但是问题来了,如要用户线程也在执行,那么就不能轻易的改变堆中对象的内存地址!不然会导致用户线程无法定位引用对象,从而无法正常运行!而标记整理算法和复制算法都会移动存活的对象,这就与上面的策略不符!因此CMS采用的是标记清理算法!
在这里插入图片描述
原来的垃圾回收算法(整理算法、复制算法)都是整体停止开始标记的,现在cms是gc的标记线程和应用自身线程同时工作,进行标记的;

过程:

  • 1、初始标记:独占PUC,stop-the-world, 仅标记GCroots能直接关联的对象

  • 2、并发标记:可以和用户线程并发执行,通过GCRoots Tracing 标记所有可达对象。(大量垃圾对象的标记是在并发阶段进行的)

  • 3、重新标记:独占CPU,stop-the-world, 对并发标记阶段用户线程运行产生的垃圾对象进行标记修正,以及更新自我拯救那部分逃逸对象

  • 4、并发清理:可以和用户线程并发执行,清理垃圾

优点:

  • 并发,低停顿

缺点:
1、对CPU非常敏感:在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分线程使应用程序变慢

2、无法处理浮动垃圾:在最后一步并发清理过程中,用户线程执行也会产生垃圾,但是这部分垃圾是在标记之后,所以只有等到下一次gc的时候清理掉,这部分垃圾叫浮动垃圾。由于并发清理的时候,用户线程也在运行,就需要保证用户线程在运行的时候需要留有部分内存以供使用。但是当这部分内存不足以给用户线程正常使用时,就会出现一次 “Concurrent Mode Failure”,一旦出现了“Concurrent Mode Failure”,便会开启后备方案,临时使用SerialOld收集器进行收集工作。

3、CMS使用“标记-清理”法会产生大量的空间碎片,当碎片过多,将会给大对象空间的分配带来很大的麻烦,往往会出现老年代还有很大的空间但无法找到足够大的连续空间来分配当前对象,不得不提前触发一次FullGC,
为了解决这个问题CMS提供了一个开关参数,用于在CMS顶不住,要进行FullGC时开启内存碎片的合并整理过程,但是内存整理的过程是无法并发的,空间碎片没有了但是停顿时间变长了

总的来说;cms为了追求短停顿,并发,未业务正常,无法整理碎片本原因是gc线程、用户线程一起跑),对内存的回收不够彻底;造成垃圾碎片,通过FullGC协助完成; 一起跑的过程还会造成用户线程的内存空间不够,只能全部停顿,用serialOld;

G1

G1:是一款面向服务端应用的垃圾收集器
初始标记–>并发标记---->最终标记---->筛选回收
G1只有并发标记阶段能做到用户线程和回收线程并发执行

G1可以不需要其它收集器配合就能独立管理整个GC堆; 因为清理阶段stop the word 可以做内存整理
目标是替换掉CMS收集器

在这里插入图片描述

特点:
1、并行与并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。

2、分代收集:分代概念在G1中依然得以保留。虽然G1可以不需要其它收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。也就是说G1可以自己管理新生代和老年代了。

3、空间整合,没有内存碎片产生:由于G1使用了独立区域(Region)概念,G1从整体来看是基于“标记-整理”算法实现收集,从局部(两个Region)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片。

在最后筛选回收阶段,对每个region里的回收对象价值(回收该区域的时间消耗和能得到的内存比值)最后进行排序,用户可以自定义停顿时间,那么G1就可以对部分的region进行回收! 这使得停顿时间是用户自己可以控制的!!!!

但是每个region之间是有互相引用的依赖关系的!这导致在MinorGC的时候会同时对老年代进行扫描(甚至是整个堆扫描),那就会导致MinorGC的效率低下,时间变长!

每个region之间是有互相引用的依赖关系的

维护一个Remebered Set集合来存放各个Region之间的引用关系!当进行GC Roots Tracing 的时候就可以只扫描set里的关联region!而不用全堆扫描啦!!!

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

可预测的停顿什么意思呢?
G1可以有计划的避免在整个JAV堆中进行垃圾收集,可以对每个region里的回收对象价值(回收该区域的时间消耗和能得到的内存比值)进行分析,在最后筛选回收阶段,对每个region里的回收对象价值(回收该区域的时间消耗和能得到的内存比值)最后进行排序,用户可以自定义停顿时间,那么G1就可以对部分的region进行回收!这使得停顿时间是用户自己可以控制的!!!!

与其它收集器相比,G1变化较大的是它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留了新生代和来年代的概念,但新生代和老年代不再是物理隔离的了它们都是一部分Region(不需要连续)的集合。同时,为了避免全堆扫描,G1使用了Remembered Set来管理相关的对象引用信息。当进行内存回收时,在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏了。

最后筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划(可预测的停顿),这一过程同样是需要停顿线程的,但Sun公司透露这个阶段其实也可以做到并发,但考虑到停顿线程将大幅度提高收集效率,所以选择停顿

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值