Java常用的垃圾收集器,Java GC 基础四——常用的垃圾回收器

0.前言

之前我们已经对JVM的内存区域,GC的回收算法,以及监控方式都做了介绍,链接如下:

接下来我们来聊一下常用的垃圾回收器。

1.基本概念

在聊具体的垃圾回收器之前,我们需要了解一些衡量垃圾回收器性能的指标,主要有以下几个:

吞吐量

指在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值。

系统总运行时间 = 应用程序耗时 + GC 耗时。如果系统运行了 100min,GC 耗时 1min,那么系统的吞吐量就是(100-1)/100=99%。

垃圾回收器负载

和吞吐量相反,垃圾回收器负载指来记回收器耗时与系统运行总时间的比值。

停顿时间

指垃圾回收器正在运行时,应用程序的暂停时间。对于独占回收器而言,停顿时间可能会比较长。使用并发的回收器时,由于垃圾回收器和应用程序交替运行,程序的停顿时间会变短,但是,由于其效率很可能不如独占垃圾回收器,故系统的吞吐量可能会较低。

垃圾回收频率

指垃圾回收器多长时间会运行一次。一般来说,对于固定的应用而言,垃圾回收器的频率应该是越低越好。通常增大堆空间可以有效降低垃圾回收发生的频率,但是可能会增加回收产生的停顿时间。

反应时间

指当一个对象被称为垃圾后多长时间内,它所占据的内存空间会被释放。

2.垃圾收集器介绍

ae8d506e76f2

常用的垃圾回收器.png

从上图中可以看出,目前常用的垃圾回收器有7个,按照工作的内存区间的不同,可以分为新生代收集器和年老代收集器。按线程数分,可以分为串行垃圾回收器和并行垃圾回收器。串行垃圾回收器一次只使用一个线程进行垃圾回收;并行垃圾回收器一次将开启多个线程同时进行垃圾回收。

2.1 新生代垃圾收集器

Serial(新生代串行收集器)

使用复制算法的垃圾回收器,只能用于新生代。Serial回收器使用单线程进行垃圾回收。

在 HotSpot 虚拟机中,使用-XX:+UseSerialGC 参数可以指定使用Serial(新生代串行收集器)+ Serial Old(老年代串行收集器)。当 JVM 在 Client 模式下运行时,它是默认的垃圾收集器。

ParNew(新生代并行收集器)

Serial回收器的多线程版本,只能用于新生代。使用复制算法,多线程并行工作。在多CPU主机上的性能高于Serial,单CPU主机上的性能低于Serial。

如果使用-XX:+UseParNewGC,表示ParNew(并行收集器)+ Serial Old(串行收集器)

Parallel Scavenge(新生代并行回收收集器)

新生代并行回收收集器也是使用复制算法的收集器。从表面上看,它和并行收集器一样都是多线程、独占式的收集器。但是,并行回收收集器有一个重要的特点:它非常关注系统的吞吐量。

在启动参数中指定-XX:+UseParallelGC,会使用Parallel Scavenge(新生代并行回收收集器) + SerialOld的回收器组合

如果使用-XX:+UseParallelOldGC,表示Parallel Scavenge(新生代并行回收收集器)+ Parallel Old(并行回收收集器)

上面介绍的三个垃圾收集器都是独占式(Stop the world)的垃圾收集器,那什么是独占式,还有别的模式吗?我们先看下图:

ae8d506e76f2

从图中可以看出,垃圾收集器根据工作模式可以分为并发式垃圾回收器和独占式垃圾回收器。并发式垃圾回收器与应用程序线程交替工作,以尽可能减少应用程序的停顿时间;独占式垃圾回收器一旦运行,就停止应用程序中的其他所有线程,直到垃圾回收过程完全结束。

2.2 老年代垃圾收集器

Serial Old 收集器

Serial收集器的老年版本,独占式,单线程,使用的是标记--整理算法,这个收集器的目的也是用于Client模式下的虚拟机使用。

Parallel Old收集器

是Parallel Scavenge收集器的老年版本,使用多线程和标记整理算法,注重吞吐量优先,在注重吞吐量和CPU资源铭感的场合,都可以考虑Parallel Scavenge加Parallel Old收集器。

CMS收集器

CMS收集器(Concurrent Mark Sweep)是一种一获取最短回收停顿时间作为目标的收集器,目前很大一部分的Java应用都集中在互联网和B/S系统上,这类应用尤其重视服务的响应速度,希望系统停顿的时间最短。 使用多线程和标记清除算法。

CMS收集器的运行过程可以分为四步:

1.初始标记:Stop the world,只标记GC Roots能直接关联到的对象。

2.并发标记:GC Roots Tracing

3.重新标记:Stop the world,修正并发标记期间,因用户程序继续运行导致标记产生变动的那一部分对象的标记记录。

4.并发清除:并发清除可以和用户线程一起运行,所以总体上停顿的时间非常短。

但是CMS收集器有三个显著缺点:

1.对CPU资源敏感。

2.无法处理浮动垃圾。

3.收集结束后会产生大量碎片:标记清除算法通病。

ae8d506e76f2

Serial Old 和CMS收集器示意图

2.3 不分代收集器

G1收集器

基于标记整理算法,所以不会产生大量的空间碎片,而且他可以非常精确的控制停顿,G1收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能极力的避免全区域的垃圾收集,之前的收集器进行收集的范围都是整个新生代或者老年代,而G1收集器将整个内存堆分为多个大小固定的独立去,跟踪这些区域里垃圾对集成度,在后台维护一个优先列表,每次根据允许的收集时间,优先收集垃圾最多的区域,区域划分及有优先级的区域回收,保证了G1收集器在有限的时间内可以获得极高的效率。

3.GC 搭配

垃圾收集器搭配总结:

CMS 只能配 Serial 或 ParNew

Parallel Scavenge 只能配 Serial Old 或 Parallel Old

Serial 不能配 Parallel Old

常用的组合有以下几种:

Serial + Serial Old (UseSerialGC): GC 线程在做事情时, 其他所有的用户线程都必须停止 (即 stop the world)

Serial + CMS: 一般不会这样配合使用

ParNew + CMS (UseConcMarkSweepGC): 新生代的 GC 使用 ParNew, 有多个 GC 线程同时进行 Minor GC (主要是在多核的环境用多线程效果会好); 而老生代使用 CMS

ParNew + Serial Old (UseParNewGC): 新生代用 ParNew 的时候, 也可以选择老生代不用 CMS, 而用 Serial Old (实际上, 这个组合也不太常用)

Parallel Scavenge + Serial Old (UseParallelGC): Parallel Scavenge 收集器的目的是达到一个可控制的吞吐率 (适用于各种计算任务); 这个组合中老生代仍旧使用 Serial Old

Parallel Scavenge + Parallel Old (UseParallelOldGC): 新生代使用 Parallel Scavenge, 而 Parallel Old 是老年代版本的 Parallel Scavenge

参考文档:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值