day3_垃圾回收器


主要有7种垃圾回收器,如下所示:
在这里插入图片描述
其中有直线关联的表示,这2种垃圾回收器可以配合使用的。

Serial回收器

Serial收集器是一个单线程的垃圾回收器,所谓的单线程,就是说,只能由一个CPU或者一个线程来进行垃圾回收,同时,在进行垃圾回收的时候,会引发STW(stop the world),暂停其他线程继续运行
主要是用于新生代的,所采用的垃圾回收算法为标记复制算法

那么使用Serial回收器,对应的优点主要是,由于他是一个单线程的,那么就不存在线程交互的开销,可以专心做垃圾回收从而获得最高的单线程收集效率。但是他的缺点是会引起STW

ParNew回收器

ParNew回收器是Serial回收器的多线程版本,除了使用多线程进行回收之外,其他的用法基本和Serial回收器相同,例如所使用的回收算法一样都是标记复制算法,同样会引起STW等

并且ParNew回收器可以配合CMS回收器一起使用的,这个是它的唯一的优点

Parallel Scavenge回收器

Parallel Scavenge回收器主要是针对新生代的,所采用的回收算法是标记复制算法。并且注重吞吐量(吞吐量 = 用户运行代码所用的时间 / (用户运行代码所用的时间 + 垃圾回收所花的时间)),通常可以通过设置参数-XX:-XX:GCTimeRatio来控制吞吐量的大小,如果值为19,那么垃圾回收所占用的时间占总时间的5%(1 / (1 + 19))

在jdk 1.5之前,主要是和Serial Old配合使用的,而在之后,就和Parallel Old配合使用。其中Serial Old, Parallel Old同样是针对的老年代,并且采用的都是标记整理算法进行回收垃圾的

Serial Old回收器

Serial Old回收器是一个单线程的,并且是针对的老年代,采用的回收算法是标记整理算法
Serial Old回收器主要用在2个地方: 在jdk 1.5之前,配合Parallel Scavenge回收器使用,其次,作为CMS回收器的一个备选方案,在并发失败之后,就会退化,使用Serial Old回收器来进行回收

Parallel Old回收器

Parallel Old回收器是一个多线程的,并且针对的是老年代,采用的是标记整理算法回收垃圾的。并且在jdk 1.5之后,配合Parallel Scavenge回收器使用的。

CMS(Concurrent Mark Sweeping)回收器

CMS回收器针对的是老年代的一个回收器,所采用的回收算法是标记清除算法
对应回收的流程为:

  • 初始标记: 仅仅标记和GC ROOT直接关联的对象。会引发STW,也即会暂停其他所有的工作线程

  • 并发标记:标记GC ROOT能够到达的对象。它是和其他用户线程并发执行的

  • 重新标记:因为在并发标记阶段,其他的用户线程继续运行,此时就有可能导致标记记录发生了变动,所以需要重新标记这一部分变动的记录。同样会引发STW

  • 并发清理:将没有被标记的对象清除,是和其他的用户线程并发执行的,那么这时候同样可能会一些浮动垃圾(就是由用户线程运行,所产生的)。
    在这里插入图片描述
    使用CMS回收器存在的问题

  • 对处理器资源非常敏感。因为在并发标记的过程中,垃圾回收线程和其他的用户线程并发执行的,那么这时候CPU的利用率并没有完全利用起来(垃圾回收线程的数目 = CPU数量 * 1/4),也即是说,如果有4个CPU,那么就有1个CPU用来进行垃圾回收的

  • 无法处理“浮动垃圾”,有可能导致并发失败而导致一次Full GC

    所谓的浮动垃圾,就是说在并发清理的过程中,其他的用户线程继续运行,这时候就会产生一些垃圾对象,由于这部分垃圾对象是在标记过程之后才产生的,所以CMS回收器并不会在这次的GC操作中回收,而需要等到下一次GC操作才会将其回收。

    在进行并发清理的这个过程中,其他的用户线程继续运行。因此需要预留一定的内存空间给这些用户线程使用,对应的策略就是通过设置参数 -XX:InitatingOccupancyPercent,一旦超过了这个值,就会执行一次垃圾回收,避免发生Full GC
    预留的内存空间依然没有满足用户程序的需要,就会发生并发失败,此时就会使用CMS的备选方案,退化使用Serial Old回收器来进行回收

  • 采用的标记清除算法,会产生大量的内存碎片,最后导致由于没有连续的内存空间,分配给对象,而导致一次Full GC。所以需要通过设置参数-XX:CMSFullGCsBeforeCompaction,表示在进行多少次CMS回收后,进行一次内存压缩。(默认值为0,表示每次FullGC都进行碎片整理)

G1

G1同样拥有低延迟和吞吐量,并且拥有超大的内存,而且将内存分为若干个大小相同的Regin.
在整体上面使用的是标记整理算法,而2个Region之间使用的标记复制算法

G1回收器的对应流程:

  • 初始标记: 标记和GC ROOT直接关联的对象。会引发STW
  • 并发标记:标记存活的对象。和其他的用户线程并发执行。
  • 最终标记:由于在并发标记的这个过程中,其他的用户线程并发执行,所以会导致标记记录发生变动,因此需要重新标记这部分变动的记录。同样会引起STW。
  • 筛选回收:会将没有标记的对象中,筛选占用内存最大的对象进行回收。

对应的流程为:
在这里插入图片描述
但是在最终标记这个阶段,它是通过写屏障 和一个对象来实现的,从而避免漏标等情况,例如下面的例子:
在这里插入图片描述
但是由于并发清理和其他用户线程是并发执行的,所以这回收的过程中,如果用户线程将B中的某一个属性的引用,指向了D对象,如下所示:
在这里插入图片描述
所以上面的D本不应该被回收,但是被回收了。所以就有了重新标记,需要加入写屏障,在某一个对象的引用发生变动的时候,就会加入一个写屏障,同时将这个对象加入到一个队列中,将这个对象标记为灰色,然后让另一个线程来扫描这个对象,发现这个对象是灰色的,就将其标记为黑色。如下所示:
在这里插入图片描述
在这里插入图片描述

参考: https://www.cnblogs.com/Chary/p/14428356.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值