JVM垃圾回收器详解(上)-CMS收集器| 8月更文挑战 J

JVM垃圾回收器详解(上)-CMS收集器| 8月更文挑战

前言: 了解垃圾收集器之前需要先了解一下垃圾收集算法,如有不了解垃圾收集算法的,点击
JVM垃圾收集算法详解前往了解

Serial收集器

serial收集器是JVM中诞生最早的一款垃圾收集器,既然是诞生的最早那么肯定有当时的一些局限性,先Serial翻译过来是连续的,顺序的,所以可以知道它是串行的,单线程收集器。它的单线程不单单是只有一条线程在进行垃圾回收,还有因为在垃圾回收的时候必须停掉其他的工作线程,也就是STW,直到它垃圾回收结束,其他工作线程才能继续进行。

垃圾回收算法: 新生代采用复制算法,老年代采用标记-整理算法。

STW:全文为Stop The World(停止世界), 说的是指,在进行GC的过程中,会产生让我感觉应用停顿的感觉,可以理解为我们平时遇到的一种卡顿过程,整个程序的工作线程都被停止,你的请求无法得到任何响应,仿佛程序停止运行了一样,这种停顿称作为STW。

image.png

 简单提一下老年代版本的Serial收集器,叫Serial Old是Serial收集器的老年代版本,它也同样是一个”单线程””的垃圾收集器。由于也是单线程,所以使用的场景也很少了既然提到了,那就说明还是有它的用途,目前主要是用在JDK1.5以前的版本与Parallel Scavenge收集器一起使用,这种场景很少了,现在基本上都是JDK1.8,再次一点是1.7或1.6,所以基本可以忽略,另外一种用途是在CMS收集器并发的阶段出现concurrent mode failure则会使用Serial Old收集器的作为后备方案。

使用参数设置:-XX:+UseSerialGC -XX:+UseSerialOldGC

Parallel Scavenge收集器

按照程序发展的一个顺序来说,单线程的既然已经有了,那么接下来就应该是多线程了,所以Parallel Scavenge收集器登场了,因此可以说是Serial收集器的多线程版本。因为在除了用多线程进行收集垃圾以外,在其它的地方与Serial收集器很类似,例如垃圾回收算法,参数设置等等。另外Parallel Scavenge最关注的是CPU中用于运行用户代码的时间与CPU总消耗时间的比值,可以称作为吞吐量,可以通过 Scavenge提供的各种参数设置,来找到自己程序最合适的一个吞吐量。

image.png

垃圾回收算法: 新生代采用复制算法,老年代采用标记-整理算法。
使用参数设置: -XX:+UseParallelGC(年轻代) -XX:+UseParallelOldGC(老年代)

ParNew收集器

ParNew收集器跟 Parallel Scavenge收集器区别不是很大,主要区别在于它可以和CMS收集器来进行配合使用,它也是目前唯一能跟CMS收集器搭配使用的,当你指定CMS收集器的时候,默认会使用ParNew收集器作为新生代收集器

image.png

使用参数设置: -XX:+UseParNewGC

垃圾回收算法: 新生代采用复制算法,老年代采用标记-整理算法。

CMS收集器

CMS收集器全称为Concurrent Mark Sweep,并行标记扫描,是一款并发的老年代垃圾收集器,年轻代默认使用ParNew收集器,GC线程与工作线程可以同时进行,并且是通过以最短停顿时间(STW)为目标的收集器,从CMS中的Mark与Sweep可以看出,主要是采用的标记-清除算法,另外CMS收集器的运行过程与前面的几种收集器有很大的不同,主要可以分为四个步骤,如下:

  • 初始标记:停止所有的GC以外的线程,也就是STW,然后通过可达性分析算法,记录GC ROOTs能直接引用的对象,这一步速度很快.
  • 并发标记:并发标记阶段主要是从出书标记中记录的GC Roots的直接关联对象开始遍历整个对象的过程,这个过程中涉及的过程比较复杂,因此耗时比较长,但因为是并发的一个流程,GC线程与工作线程同时进行,是不需要停顿工作线程。这样做带来的弊端就是,由于程序在一直运行,会导致之前标记过的对象,在并发标记过程中发生了状态改变,因此才有了接下来的重新标记。
  • 重新标记:重新标记阶段主要是为了修正并发标记过程中在初始标记阶段记录后发生状态改变的对象,使用到的是三色标记中的增量更新算法,此阶段会进行STW,停顿时间比初始标记稍长,但比并发标记阶段时间段很多。
  • 并发清理: 同时开启工作线程与GC线程,GC线程主要对未标记的区域进行一个清理,由于也是并发的过程,这个阶段也会有新增的对象被标记,那么不会对该对象做任何处理。
  • 并发重置:重置这次GC过程中的标记数据。

image.png

优点:

  1. 并发收集:整个过程中,除了初始标记与重新标记会发生外,其他过程都是并发过程。
  2. 低停顿:除开初始标记与重新标记这两个过程会发生STW停顿外,其他的三个过程中不会发生STW停顿 。

缺点:

  1. CPU资源问题:CPU使用较强,容易抢多服务CPU资源。
  2. 浮动垃圾问题:产生的浮动垃圾无法处理,如在并发标记与并发阶段中又产生垃圾那么只能等到下次GC再进行处理。
  3. 空间碎片问题:由于使用的标记-清除算法,因此在回收结束的时候会产生空间碎片问题,但是可以通过参数设置来解决,不过会消耗点性能。
  4. concurrent mode failure问题:在并发标记或并发清理阶段的时候,如果又触发了垃圾回收,但是本次垃圾回收又没进行完,那么则会触发concurrent mode failure,这时候则会进入到单线程收集,先stop the world,随后使用上文提到的serial old垃圾回收器来进行回收。

垃圾回收算法: 标记-清除算法。

使用参数设置: -XX:+UseConcMarkSweepGC

其他参数设置:

  • -XX:+UseCMSCompactAtFullCollection: 可以让jvm在执行完标记清除后再做整理,解决上文提到的空间碎片问题,类似使用标记-整理算法。
  • -XX:ConcGCThreads:设置GC的时候并发线程数
  • -XX:CMSInitiatingOccupancyFraction: 老年大使用百分比达到该值的时候会触发垃圾回收(默认是92)
  • -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW。
  • -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW。

总结

Serial收集器与Parallel Scavenge收集器都是比较久远的收集器了,随后的CMS收集器,G1收集器(下期会讲)都是更优秀的收集器,Serial的特别性在于它的老年代版本Serial Old可以作为CMS收集器在concurrent mode failure的时候的备用,而ParNew作为CMS的搭档,负责新生代的收集,CMS负责老年代的收集.

Q.E.D.

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%