垃圾收集器
如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的实践者。根据分代收集理论,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
)
- 初始标记:标记
GC Roots
能直接关联到的对象,速度很快,但存在Stop The World
停顿。 - 并发标记:从
GC Roots
的直接关联对象开始遍历整个对象图,耗时较长,但遍历线程与用户线程可并发执行。无Stop The World
停顿。 - 重新标记:修正并发标记阶段,用户线程并发执行时导致标记产生变动的那一部分对象的标记记录(增量更新),存在
Stop The World
停顿,且一般比初始标记阶段停顿时间长。 - 并发清除:清理删除掉标记阶段判断为不可达的对象,清理线程可与用户线程并发执行。
由于存在并发标记和并发清除阶段,用户线程在并发执行期间完全有可能产生新的垃圾对象,但这部分对象出现在标记过程结束之后,本次回收无法进行处理,只能等到下一次老年代内存回收时才能被清理掉,这部分垃圾被称为“浮动垃圾”。
在用户线程和收集器线程并发执行期间,是可能会有对象需要进入老年代的,这时就需要老年代预留一定的内存空间。在Java5
的虚拟机中,默认设置是老年代内存使用了68%
后就会触发CMS
收集器回收老年代。这是一个比较保守的值,可以使用参数-XX: CMSInitiatingOccu-pancyFraction
来调整这个默认值。到了Java6
时,默认设置提高到了92%
,但这又会存在一个问题,如果CMS
收集器在并发期间,预留的内存无法满足用户线程的需要,就会出现一次“并发失败”,这时,虚拟机采用降级保护方案,挂起用户线程(Stop The World
),临时启用Serial Old
老年代收集器重新进行老年代的回收。总的来说,-XX: CMSInitiatingOccu-pancyFraction
这个参数设置的太高会容易出现“并发失败”问题,性能不增反降;太低又会导致内存利用率不高,且回收频率会上升。所以,用于生产环境时应谨慎调整。
标记-清除算法不可避免的问题就是内存碎片问题,当老年代内存碎片过多时,没有连续空间来容纳大对象,即使还有很多内存没有使用,还是会触发Full GC
。CMS
收集器提供了一个-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
让虚拟机根据当前系统的运行情况收集性能监控信息,动态调整新生代大小、Eden
和Survivor
区域比例等参数以提供最合适的停顿时间或最大吞吐量。
Parallel Old
老年代收集器
吞吐量优先收集器。采用标记-整理算法,多线程并发收集。与Parallel Scavenge
新生代收集器搭配使用。
参考
- 《深入理解
Java
虚拟机:JVM
高级特性与最佳实践(第3
版)》 - 周志明