JVM垃圾收集器

原文地址:xeblog.cn/articles/24java

image

新生代收集器

新生代均采用 复制 算法来回收内存。算法

Serial 收集器

最基本的、发展历史最悠久的单线程的收集器。在进行垃圾收集时,必须暂停其它全部的工做线程(Stop The World),直到它收集结束。它是 JVM 运行在 Client 模式下的默认新生代收集器,它比其它单线程的收集器更简单、更高效。可与 CMS 收集器 配合工做。bash

ParNew 收集器

Serial 收集器 的多线程版本。它是许多运行在 Server 模式下的虚拟机首选的新生代收集器,在使用 -XX:+UseConcMarkSweepGC 选项后的默认新生代收集器,也能够经过 -XX:+UseParNewGC 选项强制指定它。它除了是多线程收集以外,其它和 Serial 收集器 基本同样,它默认开启的收集线程数与 CPU 的数量相同,在 CPU 很是多的环境下,可经过 -XX:ParallelGCThreads 参数限制垃圾收集的线程数。可与 CMS 收集器 配合工做。多线程

Parallel Scavenge 收集器

并行的多线程收集器,它的目标是达到一个可控的吞吐量(吞吐量是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值)。并发

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

高吞吐量能够高效的利用 CPU 时间,尽快的完成程序的运算任务,主要适合在后台运算而不须要太多交互的任务。Parallel Scavenge 收集器 提供了两个参数用于精确控制吞吐量: -XX:MaxGCPauseMillis-XX:GCTimeRatio性能

最大垃圾收集停顿时间:-XX:MaxGCPauseMillis

容许一个大于0的毫秒数,收集器将尽量保证内存回收花费时间不超过这个设定的值,它是以牺牲吞吐量和新生代空间来缩短 GC 停顿时间的。spa

吞吐量大小:-XX:GCTimeRatio

容许一个大于0且小于100的整数,垃圾收集时间占总时间的比率。线程

GC自适应调节参数:-XX:+UseAdaptiveSizePolicy

这是一个开关参数,当它打开后,就不须要手动指定新生代的大小(-Xmn),EdenSurvivor 区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行状况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量。3d

老年代收集器

老年代采用 标记-整理标记-清除 算法来回收内存。code

Serial Old 收集器

它是 Serial 收集器 的老年代版本,也是一个单线程收集器,使用 标记-整理 算法。这个收集器的主要意义也是在于给 Client 模式下的虚拟机使用,若是是在 Server 模式下,那么它主要还有两大用途:

  • JDK1.5 以及以前版本中与 Parallel Scavenge 收集器 搭配使用。
  • 做为 CMS收集器 的后备预案,在并发收集发生 Concurrent Mode Failure 时使用。

Parallel Old 收集器

它是 Parallel Scavenge 收集器 的老年代版本,使用多线程和 标记-整理 算法。

CMS 收集器 (Concurrent Mark Sweep)

它是一种并发的、以获取最短回收停顿时间为目标的收集器,使用 标记-清除 算法实现的。运行过程较为复杂,整个过程分为4个步骤:

  • 初始标记(CMS Initial Marking)
  • 并发标记(CMS Concurrent marking)
  • 从新标记(CMS ReMarking)
  • 并发清除(CMS Concurrent Sweep)

初始标记、从新标记仍须要暂停其它全部的工做线程,初始标记仅仅只是标记一下 GC Roots  能直接关联到的对象,速度很快。并发标记阶段就是进行 GC Roots 的可达性分析过程,而从新标记阶段则是为了修正并发标记期间因用户线程继续运做而致使标记产生变更的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但远比并发标记的时间短。CMS 收集器 存在3个明显的缺点:

  • CMS收集器 会占用一部分线程而致使应用程序变慢,总吞吐量会下降。CMS 默认启功的回收线程数是(CPU数量 + 3)/ 4 ,至关于当 CPU 在4个以上时,并发回收时垃圾收集线程很多于 25%CPU 资源,并随着 CPU 数量的增长而降低。当 CPU 不足4个时,CMS 对用户线程的影响就可能变得更大。
  • CMS收集器 没法处理浮动垃圾,可能出现 Concurrent Mode Failure 失败而致使另外一次 Full GC 的产生。因为 CMS 并发清除阶段用户线程还在运行着,伴随程序运行天然就还会有新的垃圾不断产生,这一部分垃圾出如今标记过程以后,CMS 没法在当次收集中处理掉它们,只好留在下一次 GC 时再清理掉,这一部分垃圾就称为浮动垃圾。
  • 因为 CMS收集器 使用的是 标记-清除 算法,因此垃圾回收后会产生大量的空间碎片。CMS 提供 -XX:+UseCMSCompactAtFullCollection 的开关参数(默认开启),用于在 CMS 收集器顶不住要进行 Full GC 时开启内存碎片的合并整理过程,这个过程是没法并发执行的,虽然空间碎片没了,可是停顿时间不得不变长。

全干工程师:G1收集器

G1收集器 是当今收集器技术发展的最前沿成果之一。

上面所介绍的收集器,都只是负责 Java堆 中的一部份内存(新生代或老年代),而 G1 就不一样了,它全干。
G1 将整个 Java堆 划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,可是这两部份内存再也不是物理隔离的,它们都是一部分不须要连续的 Region 的集合了。

具有的特色:

  • 并行与并发:G1 能充分利用多 CPU 、多核环境下的硬件优点,使用多个 CPU 来缩短 Stop The World 的停顿时间。
  • 分代收集(全干工程师):G1 能够不须要与其它收集器配合就能独立管理整个 GC堆,根据 分代收集 的概念采用不一样的方式去处理。
  • 空间整合:基于 标记-整理复制 算法,不会产生内存空间碎片。
  • 可预测的停顿:G1 能够创建可预测的停顿时间模型,将垃圾收集消耗的时间限制在必定的时间内。

可预测的停顿时间模型

G1 之因此可以创建可预测的停顿时间模型,是由于它能够有计划的避免在整个 Java堆 中进行全区域的垃圾收集。G1 经过跟踪各个 Region 里面的内存堆积的价值大小(回收所得到的空间大小以及回收所需时间的经验值),在后台维护一个优先回收队列,每次根据容许的收集时间,优先回收价值最大的 Region。这种使用 Region 划份内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限的时间内能够获取尽量高的收集效率。

避免全堆扫描且保证准确性

G1 收集器中,Region 之间的对象引用以及其它收集器中的新生代与老年代之间的对象引用,虚拟机都是使用 Remembered Set 来避免全堆扫描的。G1 中的每个 Region 都有一个与之对应的 Remembered Set,在对 Reference 类型的数据进行写操做的时间,虚拟机会产生一个屏障暂时中断写操做,而后检查这个引用的对象是否处于不一样的 Region 之中,若是是,就会经过 CardTable 把相关引用信息记录到被引用对象所属的 RegionRemembered Set 中。当进行内存回收时,在 GC Roots 的枚举范围内加入 Remembered Set 便可保证不对全堆扫描也不会有遗漏。

G1运行过程

若是不计算维护 Remembered Set 的操做,G1 收集器的运行过程大体能够分为4个步骤:

  • 初始标记(G1 Initial Marking)
  • 并发标记(G1 Concurrent Marking)
  • 最终标记(G1 Final Marking)
  • 筛选回收(G1 Live Data Counting And Evacuation)

初始标记阶段只是简单的标记一下 GC Roots  能直接关联到的对象,而且修改TAMS(Next Top At Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的 Region 中建立新对象,这个阶段须要停顿线程,但耗时很短。并发标记阶段也是进行 GC Roots 的可达性分析过程,耗时很长可是可与用户程序一块儿工做。最终标记阶段是为了修正并发标记期间因用户线程继续运做而致使标记产生变更的那一部分对象的标记记录,虚拟机将这段时间对象变化记录在线程的 Remembered Set Logs 中,这个阶段须要把 Remembered Set Logs 中的数据合并到 Remembered Set 里,须要停顿线程,可是能够并行执行。 最后的筛选回收阶段会对 Region 的回收价值和成本进行排序,根据用户所指望的 GC 停顿时间来制定回收计划。

查看JVM所使用的收集器

java -XX:+PrintCommandLineFlags -version
复制代码

在终端执行上述命令后,便可查看 JVM 所使用的收集器。

image

-XX:+UseParallelGC : 是虚拟机运行在 Server 模式下的默认值,打开此开关后,使用 Parallel Scavenge + Serial Old (PS MarkSweep) 的收集器组合进行内存回收。

参考

  • 《深刻理解Java虚拟机:JVM高级特性与最佳实践 第二版》
相关文章
相关标签/搜索