JVM的垃圾收集器分类

####垃圾收集器
这里写图片描述

上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。

#####Serial(连续的/'sɪərɪəl/ )收集器
serial是一个单线程的收集器,但是它的"单线程"的意义并不仅仅说明它只会使用一个CPU或者一条线程去完成垃圾收集工作,更重要的它在进行垃圾收集时,必须暂停其他所有线程的工作(这个停止的操作也叫 “Stop The World”)直到收集工作完成,serial在执行gc操作时暂停其他所有线程的操作都是虚拟机自动完成的,不需要用户手动去操作,但是如果gc时间太长,导致进程停顿时间很长,那用户肯定是非常不爽的是不~~~

操作流程图大概是这样的

serial垃圾收集在JDK1.3之前都是主流的垃圾收集器,随着JDK版本的不断发展升级,出现了更多的垃圾收集器如CMS(Concurrent Mark Sweep)、G1(Garbage First),从而减少用户的停顿时间,但是还是没办法完全消除停顿的方法。

serial收集器相对其他收集器优势的地方在于:简单而高效(与其他线程的单线程比),对于单个CPU来说,Serial收集器没有线程的切换开销,专心做垃圾收集自然可以获取最高的单线程收集效率。

serial收集的收集速度和内存的大小有很大的关系,内存越大收集时间越长,一般适用于内存相对较小的应用中,比如常见的桌面应用程序,所以serial收集器对于运行在Client模式下的虚拟机是一个很好的选择。

JVM的Client模式与Server模式

serial收集器的可配置参数

-XX:SurvivorRatio=8 设置Edon区和Survivor区的占比配置
-XX:PretenureSizeThreshold=3145728 参数设定超过对象超过多少时,分配到老年代中
-XX:+HandlePromotionFailure=true	是否允许新生代收集担保,进行一次minor gc后, 另一块Survivor空间不足时,将直接会在老年代中保留

#####ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外其他的都和Serial的工作原理是一样的。

运行图

ParNew收集器大多是运行在Server模式下的虚拟机首选的新生代收集器,其中的一个重要原因就是他可以与CMS(Concurrent Mark Sweep)收集器配套使用,CMS是HotSpot虚拟机上第一款真正意义上的的并发收集器,让收集线程和用户线程基本上是同时进行的。
不过CMS作为老年代的收集器无法与JDK1.4中新生代的收集器Parallel Scavenge收集器配套使用。因此CMS只能与Serial和Serial Old收集器一起使用。

ParNew收集器可以使用-XX:+UseConcMarkSweepGC选项后默认新生代收集器,也可以通过-XX:+UseParNewGC选项强制指定它。

ParNew通过使用多线程的方式进行回收,因此在单CPU的情况下ParNew还比不上Serial收集器,但是如果是多个CPU那效果肯定比Serial的好,理论来说ParNew设置垃圾收集线程的个数和CPU的核心一样的最好,利用率最高,可通过-XX:ParallelGCThreads设置内存回收的线程数。

#####Parallel Scavenge收集器
Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器。parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。吞吐量= 程序运行时间/(程序运行时间 + 垃圾收集时间),虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%。

Parallel Scavenge收集器参数参考

-XX:MaxGCPauseMillis	设置GC的最大停顿时间,在Parallel Scavenge 收集器下有效
-XX:GCTimeRatio	GC时间占总时间的比列,默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge 收集器时有效
-XX:UseAdaptiveSizePolicy	动态调整java堆中各个区域的大小以及进入老年代的年龄

#####Serial Old收集器
Serial Old是Serial收集器的老年代版本,它同样使用一个单线程执行收集,使用“标记-整理”算法。主要使用在Client模式下的虚拟机,它的收集示意图和Serial是一样的,参考上面的~~~

Serial Old主要用于Client模式下,如果用于Server模式下,它的主要用途在于:一个是在JDK5以及之前的版本中与Parallel Scavenge收集器配套使用,另外一个是座位CMS的备用方案。
#####Parallel Old(并行GC)收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。

在Parallel Old出现之前,如果新生代选择了Parallel Scavenge收集器,那么老年代收集器必须选择Serial Old,因为CMS没法与Parallel Scavenge配合使用。虽然Parallel Scavenge的效率很高,但是由于在老年代无法充分利用CPU硬件资源,会整体拉低服务器的性能(Serial Old是单线程的)

Serial Old收集器运行示意图

#####CMS(Concurrent Mark Sweep)收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于“标记-清除”算法实现的。目前大部分的应用都是基于B/S模式,这类应用注重于系统服务的响应速度,系统系统停顿的时间越短,以给用户带来较好的体验。

整个收集过程大致分为4个步骤
①.初始标记(CMS initial mark)
②.并发标记(CMS concurrenr mark)
③.重新标记(CMS remark)
④.并发清除(CMS concurrent sweep)

其中初始标记、重新标记这两个步骤任然需要"Stop The World"。初始标记仅仅只是标记出GC ROOTS能直接关联到的对象,速度很快,并发标记阶段是进行GC ROOTS Tracing的过程(根搜索算法阶段),会判定对象是否存活。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间会比初始标记阶段稍长,但比并发标记阶段要短。

由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以整体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

CMS收集器运行示意图

CMS收集器的优点:
并发收集、低停顿。

缺点:
1、CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。

2、CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“,失败后而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。
由于在垃圾收集阶段用户线程还需要运行,即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易导致“Concurrent Mode Failure”失败,性能反而降低。

3、CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full GC之后,跟着来一次碎片整理过程。

#####G1收集器
G1(Garbage First)收集器是JDK1.7提供的一个新收集器,它是基于CMS收集器的显著改进

1、G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片,这对于运行时间长的应用来说非常重要。

2、G1收集器可以实现在不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于G1极力避免全区域的垃圾收集,之前的收集器都是收集新生代和老年代,而G1把java堆划分为多个大小固定的独立区域(Region),并且跟踪这些区域里面垃圾的堆积程度,在后台维护一个优先列表,每次根据收集的时间,优先回收垃圾最多的区域(这就是Garbage First的由来),区域划分以及有优先级的区域回收,保证了G1收集器在有限的时间内可以获取最高的收集效率。

3、G1可以精确的控制停顿时间,控制在毫秒级别,基本都做到准实时回收了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值