如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的实践者。根据分代收集理论,HotSpot虚拟机提供了多种作用于不同分代的垃圾收集器,它们是不同时代的思想汇聚。

Serial新生代收集器

最基础且历史最悠久的收集器,曾是HotSpot虚拟机新生代区域的唯一选择。它选用的是标记-复制算法,单线程收集,当它开始工作时,其它工作线程必须挂起,直到它回收内存完毕。Stop The World无法避免。但好处是单线程工作,对于核数较少的处理器来说,没有线程的上下文切换开销,收集效率高,适用于客户端模式的虚拟机。

Serial Old老年代收集器

Serial新生代收集器配合使用,回收老年代,同样使用单线程收集,选用的是标记-整理算法,适用于客户端模式的虚拟机。

ParNew新生代收集器

ParNew新生代收集器实质是Serial收集器的多线程并行版本,在多核处理器的虚拟机上效率会大幅提高。选用的同样是标记-复制算法。它的特点是:除了Serial收集器外,目前只有它能与CMS收集器配合工作。大部分服务端模式的虚拟机选用该收集器回收新生代。

CMS老年代收集器

CMS (Concurrent Mark Sweep:并发标记-清除)收集器是一种以获取最短回收停顿时间(Stop The World)为目标的收集器。它的回收过程分为四个阶段:

  • 初始标记(CMS initial mark
  • 并发标记(CMS concurrent mark
  • 重新标记(CMS remark
  • 并发清除(CMS concurrent sweep
  1. 初始标记:标记GC Roots能直接关联到的对象,速度很快,但存在Stop The World停顿。
  2. 并发标记:从GC Roots的直接关联对象开始遍历整个对象图,耗时较长,但遍历线程与用户线程可并发执行。无Stop The World停顿。
  3. 重新标记:修正并发标记阶段,用户线程并发执行时导致标记产生变动的那一部分对象的标记记录(增量更新),存在Stop The World停顿,且一般比初始标记阶段停顿时间长。
  4. 并发清除:清理删除掉标记阶段判断为不可达的对象,清理线程可与用户线程并发执行。

由于存在并发标记和并发清除阶段,用户线程在并发执行期间完全有可能产生新的垃圾对象,但这部分对象出现在标记过程结束之后,本次回收无法进行处理,只能等到下一次老年代内存回收时才能被清理掉,这部分垃圾被称为“浮动垃圾”。

在用户线程和收集器线程并发执行期间,是可能会有对象需要进入老年代的,这时就需要老年代预留一定的内存空间。在Java5的虚拟机中,默认设置是老年代内存使用了68%后就会触发CMS收集器回收老年代。这是一个比较保守的值,可以使用参数-XX: CMSInitiatingOccu-pancyFraction来调整这个默认值。到了Java6时,默认设置提高到了92%,但这又会存在一个问题,如果CMS收集器在并发期间,预留的内存无法满足用户线程的需要,就会出现一次“并发失败”,这时,虚拟机采用降级保护方案,挂起用户线程(Stop The World),临时启用Serial Old老年代收集器重新进行老年代的回收。总的来说,-XX: CMSInitiatingOccu-pancyFraction这个参数设置的太高会容易出现“并发失败”问题,性能不增反降;太低又会导致内存利用率不高,且回收频率会上升。所以,用于生产环境时应谨慎调整。

标记-清除算法不可避免的问题就是内存碎片问题,当老年代内存碎片过多时,没有连续空间来容纳大对象,即使还有很多内存没有使用,还是会触发Full GCCMS收集器提供了一个-XX: +UseCMS-CompactAtFullCollection开关参数(默认开启,Java9废弃)用于在CMS收集器不得不进行Full GC时开启内存碎片的整理过程,此过程需要移动对象,无法进行并发,出现Stop The World停顿。同时CMS收集器还提供了-XX: CMSFullGCsBefore-Compaction参数(默认值为0:每次Full GC都进行碎片整理)要求收集器在执行过指定次数不整理碎片的Full GC后,下一次进入Full GC前先进行碎片整理。

Parallel Scavenge新生代收集器

吞吐量优先收集器。采用标记-复制算法。提供开关参数-XX: +UseAdaptiveSizePolicy让虚拟机根据当前系统的运行情况收集性能监控信息,动态调整新生代大小、EdenSurvivor区域比例等参数以提供最合适的停顿时间或最大吞吐量。

Parallel Old老年代收集器

吞吐量优先收集器。采用标记-整理算法,多线程并发收集。与Parallel Scavenge新生代收集器搭配使用。

参考

  • 《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》 - 周志明