JVM之垃圾收集器

Posted wangweiminll

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM之垃圾收集器相关的知识,希望对你有一定的参考价值。

Serial收集器:

采用复制算法,作用区域为新生代,是一个单线程的收集器。它执行收集工作时,只使用一个CPU或一条收集线程去完成垃圾收集工作,在执行工作期间,暂停其他所有的工作线程(Stop The World),直到它收集结束。是虚拟机运行在Client模式下的默认新生代收集器,因为:

应用程序小,JVM管理的内存回收时间相应就少;高单线程收集率,没有线程切换的开销,简单高效。

运行示意图:

 

ParNew收集器:

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余特性都一样。

它是许多运行在Server模式下的虚拟机中首选的新生代虚拟机,其中一个最重要的原因(与性能无关)是,除了Serial收集器外目前只有它能与CMS收集器配合工作。

运行示意图:

 

Parallel Scavenge收集器:

Parallel Scavenge收集器是一个新生代收集器,使用复制算法,并行的多线程收集器。

与其他收集器不同的是Parallel Scavenge收集器的关注点是达到一个可控制的吞吐量(CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值。

停顿时间短适合与用户交互的程序;高吞吐量则可以高效地利用CPU时间,尽快完成程序的运算任务,适合在后台运算不需要太多交互的任务。Parallel Scavenge收集器提供了两个参数用于精准控制吞吐量,-XX:MaxGCPauseMillis,-XX:GCTimeRatio.

Serial Old收集器:

Serial Old收集器是Serial收集器的老年代版本,单线程,使用“标记-整理”算法。这个收集器的主要意义也是在于给Client模式下的虚拟机使用。

在Server模式下,在JDK1.5之前与Parallel Scavenge收集器搭配使用,以及作为CMS收集器的后备预案。

Parallel Old收集器:

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。优先用在注重吞吐量以及CPU资源敏感的场合。

收集示意图:

 

 

CMS收集器(Concurrent Mark Sweep):

一种以获取最短回收停顿时间为目标的收集器。使用“标记-清除”算法,整个收集过程分为以下四个步骤:

1.初始标记:Stop The World

仅仅只是标记一下GC Roots能直接关联到的对象,速度快;

2.并发标记:

进行GC Roots Tracing的过程

3.重新标记:Stop The World

修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记时间短。

4.并发清除:

整个过程中耗时最长的并发标记和并发清除过程,收集器都可以和工作线程并发运行。所以总体上,CMS收集器内存回收的过程与用户线程并发执行的。

运行示意图:

优点:并发收集,低停顿

缺点:

1.CMS收集器对CPU资源非常敏感,即并发回收内存时会占用一部分CPU资源,导致应用程序变慢。

2.CMS收集器无法处理浮动垃圾(CMS并发清理阶段新产生的垃圾,需要预留内存来保证应用程序的正常运行),可能出现"Concurrent Mode Failture"失败而导致的另一次Full GC的产生(预留的空间太小,无法满足程序需要)。这时虚拟机将启动后备预案:临时启用Serial Old收集起来重新进行老年代的垃圾收集,这样停顿时间加长。

3.CMS收集器采用“标记-清除”算法的缘故,会产生空间碎片。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactStFullCollection开关参数,用于在CMS收集器顶不住要进行Full GC时开启内存碎片的整理过程,内存整理的过程是无法并发的,空间碎片没有了,单停顿时长了。

 

G1收集器

G1是面向服务端应用的垃圾收集器。具有以下特点:

1.并行与并发:使用多个CPU回收内存,缩短Stop The World停顿的时间,回收内存时工作线程可以并发执行;

2.分代收集:自已管理一个java堆,采用不同的方式回收内存,分代的概念仍然存在;

3.空间整合:整体上来看使用的是“标记-整理”算法,从局部来看使用的是“复制”算法。

4.可预测的停顿:追求低停顿时间,还能建立可预测的停顿时间模型,能让使用者指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。

使用G1收集器时,Java堆的内粗布局与其它收集器有很大差别,它将Java堆分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是隔离的了,它们都是一部分Region的集合。

G1收集器之所以能够建立可预测的时间停顿模型,是因为他可以有计划的避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(这就是Garbage-First)。

在G1收集器中,Region之间的对象引用以及其它收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remembered Set来避免全堆扫描的。Remembered Se记录了该Region中的对象被其它Region中的对象引用的情况。

G1收集器大致分为一下几个步骤:

1.初始标记:与CMS收集器对应的阶段相似

2.并发标记:与CMS收集器对应的阶段相似

3.最终标记:与CMS收集器对应的阶段相似,除此之外,虚拟机将这段时间对象的变化记录在线程Rememebered Set Logs里面,并将Rememebered Set Logs里面的数据合并到Remembered Set里面。

4.晒算回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。

 

 

执行示意图:

 

 

各个收集器合作关系图:

 

以上是关于JVM之垃圾收集器的主要内容,如果未能解决你的问题,请参考以下文章

JVM之垃圾收集器

JVM之垃圾收集器

理解JVM之垃圾收集器详解

JVM之GC算法的实现(垃圾回收器)

理解JVM之垃圾收集器概述

JVM之垃圾收集器 (GC) 与内存分配策略