垃圾收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现。
1、Serial 收集器
该收集器是最基本、发展历史最悠久的收集器,这个收集器是一个单线程的收集器,它在工作时只会使用一个CPU或一条收集线程去完成垃圾收集工作,而且它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束;Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择;
2、ParNew 收集器
ParNew收集器其实就是Serial收集器的多线程版本,它是许多运行在Server模式下的虚拟机首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器之外,目前只有它能与CMS收集器配合工作;它实现了让垃圾收集线程与用户线程基本上同时工作;
3、Paraller Scavenge 收集器
CMS等收集器关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而该收集器的目标则是达到一个可控制的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间));
4、Serial Old 收集器
Serial Old 是Serial 收集器的老年代版本,它同样是一个单线程收集器,使用标记整理算法,这个收集器的主要意义也是在于给Client模式下的虚拟机使用;
5、Paraller Old 收集器
Paraller Old 收集器是Paraller Scavenge 收集器老年代版本,使用多线程和标记整理算法
6、CMS 收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器;CMS收集器是基于标记清除算法实现的,它的运作过程分为4个步骤:
初始标记、并发标记、重新标记、并发清除
其中,初始标记、重新标记这两个步骤需要“Stop The World”。初试标记只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长,但远比并发标记时间短,由于整个过程中耗时最长的并发标记和并发清楚过程收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
CMS收集器有3个明显缺点:
- CMS收集器对CPU资源非常敏感,CMS默认启动的回收线程数是(CPU数量+3)/4,但CPU不足,例如只有2个时,CMS对用户程序的影响就变得很大;
- CMS无法收集浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次 Full GC 的产生;浮动垃圾:由于CMS在收集时,用户线程还在运行,这样一部分被标记为垃圾的无法被现在清楚,只能等待下一次GC时再收集,这部分垃圾被称为浮动垃圾;Concurrent Mode Failure:CMS收集器不能像其它收集器等到老年代几乎完全被填满再进行收集,默认下当老年代使用了68%的空间后就会开始收集,如果在收集期间,预留剩下的容量不能满足程序需要会出现Concurrent Mode Failure,这时候将会临时启用Serial Old 收集器来重新进行老年代的垃圾收集;
- CMS是一款基于标记清除算法实现的垃圾收集器,这表明它在进行垃圾收集时会产生大量的内存碎片,会为以后分配大对象带来麻烦,当无法为大对象分配空间时会触发Full GC ,可以设置参数,当需要进行Full GC 时先进行一次内存碎片的合并整理;
- 并行与并发:G1能使用多个CPU来缩短Stop-The-World停顿的时间
- 分代收集
- 空间整合:G1从整体来看是基于标记整理算法实现的收集器,从局部(两个Region之间)来看是基于复制算法实现的,所以不会产生空间碎片
- 可预测的停顿:G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒
- G1将整个Java堆划分为多个大小相等的独立区域(region),虽然还保留新生代和老年代的概念,但是新生代和老年代不再是物理隔离的,它们都是一部分region的集合