Java虚拟机详解(四)------你知道有哪些垃圾收集器吗?

时间:2019-09-06 来源:www.mdjtour.com

在之前的博客中,我们介绍了Java虚拟机垃圾收集,并介绍了几种常见的垃圾收集算法,包括标记清除,标记和复制。我们说如果这些算法是一种内存回收方法,那么在Java虚拟机中,谁将实现这些方法呢?

这是对的,这是这个博客的内容 - 垃圾收集器。

1.垃圾收集器的类型

Java虚拟机规范没有关于如何实现垃圾收集器的任何规则。因此,不同供应商提供的垃圾收集器和不同版本的虚拟机将是不同的,并且通常根据用户自己的应用程序为用户提供参数。功能和要求结合了每个时代使用的收藏家。

下图基于Sun HotSpot虚拟机1.6 Update 22虚拟机类型:

从上图中我们可以总结出几个结论:

1.新一代垃圾收集器:Serial,ParNew,Parallel Scavenge;

老年垃圾收集器:Serial Old(MSC),Parallel Old,CMS;

整个垃圾收集器:G1

2,垃圾收集器之间的连接可以一起使用,有几种组合:

Serial/Serial Old,Serial/CMS,ParNew/Serial Old,ParNew/CMS,Parallel Scavenge/Serial Old,Parallel Scavenge/Parallel Old,G1;

3,串口采集器Serial:Serial,Serial Old

Parallel Collector Parallel:Parallel Scavenge,并行收集线程以完成工作。

③、进行垃圾收集时,必须暂停所有工作线程

也就是说,当使用串行收集器进行垃圾收集时,其他工作线程被挂起,此时系统会出现干扰现象。

④、适用场景

由于没有线程交互开销,因此串行收集器可以为符合单个CPU的环境实现最高的单线程收集效率。

通常,在用户的桌面场景中,分配给虚拟机管理的内存一般不是很大,收集几十兆字节或一百二百兆字节的新一代,固定时间可以控制在几十毫秒,因为它不经常发生这种暂停是可以接受的。

因此,串行收集器是在客户端模式下运行的虚拟机的理想选择。

3,ParNew收藏家

这个收集器实际上是串行收集器的多线程版本。

换句话说,它的功能与串行收集器相同。事实上,这两个收藏家分享了很多代码。

①、作用于新生代

新一代垃圾收集器,使用的垃圾收集算法是复制算法。

②、多线程

弥补Single Collector单线程的缺点。

③、使用场景

由于其多线程特性,大多数以服务器模式运行的虚拟机都优先于新一代垃圾收集器。

还应注意,下面将描述的划时代的垃圾收集器CMS(Concurrent Mark Sweep)的使用也是一个重要原因。

4.并行清除收集器

前面描述的垃圾收集器焦点是在垃圾收集期间最小化用户线程暂停时间。 Parallel Scanvenge收集器旨在实现受控吞吐量。

吞吐量 = 运行用户代码的时间 / (运行用户代码的时间+垃圾收集时间)

它可以通过以下两个参数进行精确控制:

-XX: MaxGCPauseMills设置最大垃圾收集暂停时间

-XX: GCTimeRatio设置吞吐量大小

①、作用于新生代

新一代垃圾收集器,使用的垃圾收集算法是复制算法。

②、多线程

并行多线程垃圾收集器。

③、吞吐量

该收集器提供精确的吞吐量控制。

④、适用场景

设置垃圾收集暂停时间对于需要与用户快速交互的程序来说很短;

设置高吞吐量可以最有效地利用CPU效率,并尽快完成程序的计算任务。它主要适用于在后台不需要太多交互的任务。

5,Serial Old Collector

Serial Old收集器是Serial收集器的旧版本,具有以下功能:

①、作用于老年代

②、单线程

③、使用标记-整理算法

④、进行垃圾收集时,必须暂停所有工作线程

6,并行旧收藏家

Parallel Old是Parallel Scavenge收集器的旧版本,它使用多线程和“标记 - 完成”算法。

①、作用于老年代

②、多线程

③、使用标记-整理算法

除了上述特性之外,更重要的是将Parallel Scavenge配置与新一代收集器一起使用以最大化吞吐量。

7,CMS收集器

CMS,Concurrent Mark Sweep的全名,顾名思义,使用标记清除算法。此收集器也称为并发低暂停收集器

这是一个跨年龄的垃圾收集器,当垃圾收集线程(基本上)与用户线程一起工作时,它真正起作用。串行收集器的停止收集器(当母亲清理房间时,你不能再把垃圾扔到地上)。相比真正的母亲,在打扫房间时,你扔垃圾。

①、作用于老年代

②、多线程

③、使用标记-清除算法

整个算法过程分为以下四个步骤:

一,初始标记(CMS初始标记):只标记GC Root可以直接关联的对象,速度非常快,但需要“停止世界”

CMS并发标记:执行GC根跟踪的过程只是遍历在初始标记阶段标记的幸存对象,然后继续递归标记这些对象可到达的对象。

三,重新标记(CMS备注):在校正并发标记期间,由于用户程序导致标记发生变化的对象部分的标记记录继续运行,需要“停止世界”。此时间通常比初始标记长,但比并发标记短得多。

4. CMS并发扫描:清除上一步中标记的对象。

由于整个过程最耗时的操作是第二个(并发标记),四个步骤(并发清理),以及垃圾收集器线程的两个步骤可以与用户线程一起工作。总的来说,CMS垃圾收集和用户线程是同时执行的。

缺点:

①、对CPU资源敏感

因为在并发阶段,它将消耗一部分CPU资源,导致应用程序减速并且总吞吐量减少。

②、产生浮动垃圾

由于用户线程在CMS并发清理阶段仍在工作,此时生成的垃圾,CMS无法在此集合中处理它们,并且只能在下一个GC中处理。这部分垃圾被称为“浮动垃圾”。

③、产生内存垃圾碎片

因为使用的算法是标记清晰的,所以很明显会产生空间碎片。

8,G1收藏家

这是当前收集器技术发展的最前沿。可以在不牺牲吞吐量的情况下实现低内存内存回收。

这是因为它没有区分如上所述的所有垃圾收集器与新一代,旧时代,它作用于整个区域。将整个Java堆划分为多个固定大小的独立区域(Regin),跟踪这些区域的垃圾堆积区域,在后台维护优先级列表,并根据允许的收集时间优先回收大部分垃圾区域。它确保G1收集器可以在有限的时间内实现最高的收集效率。

它比前面描述的CMS垃圾收集器有两个重大改进:

①、采用 标记-整理 的回收算法

这不会产生空间碎片

②、可以精确的控制停顿时间

它允许用户显式指定长度为M毫秒的时间片,并且在垃圾收集上花费的时间不超过N毫秒。

3.代理整个Java堆

G1收集器不区分年轻和老一代,是一大堆垃圾收集器。

9,如何选择垃圾收集器

详细的文档可以在官方介绍中找到,如下

在这里我们翻译结论:

除非应用程序具有相当严格的暂停时间要求,否则让JVM选择垃圾收集器本身。并且可以适当调整堆的大小以提高性能。如果不符合要求,则以下四点用作指南:

1.如果应用程序内存小于100M,请使用该选项选择串行收集器-XX: + UseSerialGC。

2.如果应用程序将在单核处理器上运行且没有暂停时间要求,请选择Serial -XX: + UseSerialGC或JVM以选择

3.如果允许暂停时间超过1秒,请选择Parallel或JVM以自行选择

4.垃圾收集线程并行工作,但用户线程仍在等待。

适用于弱交互场景,如科学计算和后台处理。

②、并发

用户线程与垃圾收集器线程同时执行(但不一定并行,可以交替),用户线程继续执行,垃圾收集线程在另一个CPU上运行。

适用于Web等快速响应方案。

③、停顿时间

垃圾收集器执行垃圾收集以中断应用程序的执行时间。

④、吞吐量

吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾收集时间)

http://www.whgcjx.com/bdsma.html