【JVM】之垃圾回收器

目录

垃圾回收器

垃圾回收器的分类

GC性能指标

HotSpot垃圾回收器

Parallel Scavenge回收器(JDK1.8默认使用):吞吐量优先

Parallel Scavenge特点:

Parallel是并行的垃圾回收器,吞吐量很高,适应场景:

Parallel Old特点

CMS垃圾回收器

概述

垃圾回收过程

三色标记算法

CMS垃圾回收的时机

总结

G1回收器

概述

为什么名字叫做 区域化分代式(G1)呢?

收集过程

G1的优点

G1的缺点

G1总结


垃圾回收器

垃圾回收算法是一些针对不同的区域不同的场景设计的合理方法,而垃圾回收器是这些算法的执行者。

垃圾回收器的分类

根据线程的数量来分:

单线程(串行)垃圾回收器 :Serial、Serial Old;

多线程(并行)垃圾回收器:Parnew、Parallel Scavenge、Parallel Old。

根据工作内存来分:

新生代垃圾回收器:Serial、Parnew、Parallel Scavenge;

老年代垃圾回收器:Serial Old、Parallel Old、CMS。

根据工作模式分:

独占式垃圾回收器:Serial、Parnew、Parallel Scavenge;

并发式垃圾回收器:CMS、G1。

GC性能指标

STW时间 : (“Stop The World”)垃圾回收时暂停用户线程的时间。

吞吐量 : 用户线程运行时间/(用户线程运行时间+垃圾回收时间)。

垃圾收集开销:吞吐量的补数,垃圾回收时间/用户线程运行时间+垃圾回收时间。

内存占用:Java堆区多占用的内存大小。

快速:一个对象从诞生到被回收的时间。

GC性能指标主要看吞吐量STW停顿时间。并且吞吐量和STW停顿时间是相互矛盾的,只能折中考虑。

各个垃圾回收器的特点也不一样,有的追求吞吐量,有的追求STW停顿时间。一般在不同的场合采用不同的垃圾回收器。比如与用户交互较多的场景中追求低延迟,因此要求STW时间较少;而后台程序就比较追求吞吐量。

HotSpot垃圾回收器

图中展示了 7 种作用于不同分代的收集器,如果两个收集器之间存在连线, 则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。

 

Parallel Scavenge回收器(JDK1.8默认使用):吞吐量优先

Parallel Scavenge又称Parallel。Paralle并行;Scavenge捡破烂,拾荒

Parallel Scavenge特点:

1.年轻代使用复制算法、并行回收、STW机制。 2.吞吐量可控制。 3.拥有自适应调节策略(能够根据程序需求自动分配内存空间)。 4.回收年轻代的并行垃圾回收器。

Parallel是并行的垃圾回收器,吞吐量很高,适应场景:

适合与用户交互较少,后台计算的场景。 例如:执行批量处理、订单处理、工资支付等等,或者服务器端。

Parallel Old特点

作用在老年代,和Parallel配合使用 采用标记-压缩算法、并行回收、STW机制

CMS垃圾回收器

概述

CMS(Concurent Mark Sweep)收集器,是追求低停顿,与用户线程并发执行的收集器。

是一款首创的与用户并发运行的收集器。

垃圾回收过程

 

初始标记: STW(时间较短),使用一条初始标记线程对GCRoots直接关联的所有对象进行标记。

并发标记:与用户线程并发执行,此阶段进行可达性分析,标记处所有垃圾对象。

重新标记:STW(时间较短),使用多条标记线程,将刚刚没有标记的垃圾对象全部标记出来。

并发清除:只使用一条GC线程与用户线程并发执行,清理所标记出来的垃圾对象。此过程比较耗时。(多线程都比较耗时)。

CMS的俩个阶段采用并发执行,是为了追求低延迟,在垃圾回收的同时也要处理用户请求。

CMS优点: 可以并发收集,低延迟。

CMS缺点:

CMS基于标记-清除算法,因此会产生内存碎片,当大作业到来时,可能会提前触发Full GC。

CMS在并发阶段,耗时较长,总吞吐量会降低。

CMS无法清理浮动垃圾

PS:标记-清除算法会产生垃圾碎片,那么会什么不适用标记-压缩算法呢?

标记-压缩算法是需要移动对象的,但是CMS在清理垃圾的时候是与用户线程并发执行的。

浮动垃圾:CMS标记垃圾和清除垃圾都是和用户线程并发执行,这时用户线程产生的新垃圾对象就是浮动对象。这些对象在本次垃圾回收是无法被清理掉的。

三色标记算法

由于CMS使用并发执行,其他用户线程就可能会使原来标记的引用链改变,针对这个问题,CMS采用三色标记算法,将所有对象分为3中颜色(对应三种状态)。

黑色:例如GCRoots根对象,该对象已经被标记过了,并且该对象的所有属性也被标记了(这些属性被标记为灰色)。

灰色:对象已经被垃圾回收器 扫描过了,但其下的属性还没有被标记,这些对象被标记为灰色。

白色:过完整的标记算法后还没有被标记的对象就是不可触及的,被标记为白色,认定为垃圾。

过程

1.刚开始,GCRoots会被标记为黑色。

2.将GCRoots直接关联的对象标记为灰色。

3.将灰色标记为黑色,并且这些灰色对象的直接关联对象标记为灰色。

4.重复2、3步骤,直至没有灰色对象为止。

5.黑色对象判定为存活对象,白色的判定为垃圾。

这个过程在进行的时候,其他用户线程也会进行,就有可能出现漏标与错标的问题。

漏标

比如现有三个对象A、B、C,当A为黑色对象,B为灰色对象时,GC线程扫描B对象时,其他用户线程断开了A和B之间的引用关系(并且其他地方没有引用B),按道理B以及它的属性都应该判定为垃圾对象,但是垃圾回收器在扫描B,B已经是灰色对象,所以它会被判定为黑色,它的恶属性被判定为灰色,这种情况就会把B漏标,垃圾回收时,也不会被清理。

错标

比如现有三个对象A、B、C,当A为黑色对象,B为灰色对象时,GC线程扫描B对象之前,用户线程将C引用赋给了A,并且断开了与B的关联,这是GC线程扫描B是就无法触及到C,A为黑色对象,GC线程本次也不会扫描了,就会导致C对象变成不可触及的垃圾对象。在其他用户线程再次访问C对象时,发现找不到,就会报空指针异常。

解决错标的方法

上述错标问题,有俩部分原因共同造成,只要打破这俩个条件之一,就能够阻止错标的发生。

原始快照:当灰色对象与白色对象断开连接时,将这条记录下来,扫描结束后,将记录中的灰色对象再次扫描。

增量更新:当黑色对象与白色对象建立连接时,将这条记录下来,扫描结束后,将记录中的黑色对象再次扫描。

CMS垃圾回收的时机

由于CMS采用并发的手段,虽然低延迟,但是整个回收过程较长,并且由于垃圾回收的同时用户线程依然会申请内存,那么就不能等到内存不足时才开始。

堆内存达到一定的阈值时,就要开始垃圾回收。如果JVM预留的内存无法满足用户进程的需要,那么就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启用备用方案:启用Serial Old来对老年代回收,这样STW就会很长。

总结

CMS中的GC作为守护线程与用户线程并发执行,由于用户线程随时会更改随想的引用关系,就增大了CMS的工作负担,因此CMS较为复杂。解决这个问题CMS引入了三色标记算法,将这些引用关系的修改记录下来,以便在重新标记阶段再次扫描修正引用关系。

由于CMS仍然存在很多缺陷,所以JVM没有将CMS作为默认垃圾回收器,但CMS已经开辟了GC与用户线程并发执行的先河。

G1回收器

概述

G1(Garbage First):是一款垃圾优先的回收器,是能够降低STW时间同时兼顾了吞吐量的“全功能收集器”。它是面向服务器端的回收器。

为什么名字叫做 区域化分代式(G1)呢?

因为G1将堆内存分为很多更小的(Region)区域(物理上不连续,逻辑上连续),然后有计划地对堆内存进行垃圾回收,回收时,优先回收垃圾最多的区域。即采用垃圾优先(Garbage First的原则。

G1是一款面向服务器端应用的垃圾回收器,主要针对多核CPU以及内存较大的机器,能够满足STW时间的前提下还能兼顾高的吞吐量。因此对机器的性能也有很高的硬性要求。

收集过程

收集过程的标记阶段与CMS的基本相同,但是在回收阶段,是单线程执行,暂停其他线程,在一定的时间内对回收价值大的区域进行垃圾回收。

适用场景:对STW时间有一定的控制,内存大的应用。

G1的优点

1.并行与并发

并行:多个GC线程同时工作。

并发:部分工作与用户线程交替并发执行,因此不会再整个回收阶段出现完全发生阻塞的情况。

2.分代收集

虽然G1将堆内存分为多个Region,但是这些Region在逻辑上依然区分新生代和老年代。并且G1既可以回收年轻代也可以回收老年代。而在物理结构上,整个年轻代或者老年代是连续的。

3.空间整合

G1是以Region为单位进行的,在Region采用复制算法,但是整体上可以看做是标记-压缩算法的,这里种算法都可以整理内存碎片,这种特性有利于程序的长时间运行,大大降低了分配大对象时没有足够连续的内存空间而触发GC的概率。

java对空间越大,G1的优势更明显。

4.可预测的停顿时间模型

G1除了追求低停顿意外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M的时间内,垃圾回收的时间最多为N。

由于分区的原因,G1每次的垃圾回收只针对部分区域,缩小了垃圾回收的范围,这对于全局停顿时间的控制也能得到很好的控制。

G1跟踪各个Region里面的垃圾堆积价值大小,并维护一个队列,每次选择一个价值最大的Region进行回收。这样保证了G1垃圾回收效率,在有限的时间内可以获取更高的收集效率。

G1的缺点

相比较于CMS,G1还不具备全方位、压倒性的优势。不如在用户线程运行过程中,G1额外的占用内存以及额外执行负载都比CMS要高。

G1会对年轻代频繁的GC,在GC过程会Eden区扫描,但是有些新对象是被老年区的对象所引用,但是G1不可能对所有对空间都进行扫描,那样就失去了分区的意义。因此,G1使用了一个Remeber Set来记录引用关系,而Rset也是占用堆内存的。

在垃圾回收时,如果用户线程改变了年轻代的引用关系,为了确保引用关系的正确的同时保证吞吐量,还需要用Dirty Card Queue(脏卡队列)来记录引用关系。

对于小内存的应用,CMS的性能会比较表现会大概率优先于G1。

G1总结

G1是一款保证低延迟的前提下,有保证了更大的吞吐量,是一款“全功能垃圾回收器”。JDK9版本用G1淘汰了CMS。内存空间越大,G1的优势越明显,更适合与内存较大的场景。符合内存造价越来越低的大环境。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值