Serial收集器
它是新生代收集器,采用复制算法,只开启一条GC线程,在垃圾收集过程中需要暂停所有用户线程。该收集器适合客户端使用,因为客户端内存和堆都较小,用户感觉不到明显的停顿。
Serial的优点在于只开启一条收集线程,避免上下文切换,简单高效。
ParNew收集器
ParNew是Serial收集器的多线程并行版本,采用复制算法,同样是新生代收集器。同样在进行回收时需要暂停所有用户线程。
除了Serial收集器,只有ParNew收集器才能与CMS搭配使用。
并行处理器:描述的是多条垃圾收集器线程并行进行,通常用户线程是等待状态。
并发处理器:描述的是GC线程和用户线程之间是并发的,用户线程并未暂停。
Parallel Scavenge收集器
它也是新生代收集器,采用复制算法,也是并行收集。与其他收集器的不同在于其他收集器会尽量缩短用户线程暂停时间,而该收集器目标是使吞吐量达到可控制的量。
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。
Serial Old收集器
Serial收集器的老年代版本,同样是单线程GC,但是采用标记-整理算法。
Parallel Old收集器
Parallel收集器的老年代版本,基于标记-整理法实现。
CMS收集器
CMS基于标记-清除法实现,以获取最短停顿时间为目标。
收集过程分为四个步骤:
1、初始标记:初始标记时需要“Stop The World”,只使用一条标记线程,该阶段标记GC Roots能直接关联到的对象。
2、并发标记:从GC Roots直接关联的对象开始遍历整个对象图,使用多条线程,耗时较长但不需要暂停用户线程。
3、重新标记:目的是修正并发标记期间因用户线程运行而导致的部分对象标记的变动,使用多条线程,需要“Stop The World”。
4、并发清除:清除标记阶段判断的死亡的对象,使用一条线程,由于不需要移动存活对象,这个阶段也是和用户线程并发的。
CMS收集器的三个缺点:
1、吞吐量低:在涉及并发的阶段由于垃圾回收会占用CPU一定的运算能力,从而降低吞吐量。
2、无法处理“浮动垃圾”:“浮动垃圾”是并发阶段产生的垃圾中,在标记结束后产生的那部分垃圾,这部分垃圾无法在当次GC中被处理。
无法处理这部分垃圾可能会导致“Concurrent Mode Failure”异常而导致一次“Stop The World”的Full GC。
3、使用标记-清除法可能会产生大量的空间碎片。
Garbage First处理器
简称G1处理器,是面向服务端的收集器。G1没有区分新生代和老年代,而是把堆分成多个大小相等的独立空间Region,每个空间根据需要扮演新生代或老年代的空间。Region还有一类Humongous区域,用于存放大对象,超出Region大小的对象会被放在几个连续的Humongous中。
从整体上看, G1 是基于“标记-整理”算法实现的收集器,从局部(两个 Region 之间)上看是基于“复制”算法实现的,这意味着运行期间不会产生内存空间碎片。
跨Region可达性分析:每个Region中都维护了记忆集,记录了自身和别的Region之间的引用。避免了可达性分析时对整个堆进行扫描。
G1收集器的大致步骤:
1、初始标记:Stop The World,仅使用一条初始标记线程对所有与 GC Roots 直接关联的对象进行标记。
2、并发标记:使用一条标记线程与用户线程并发执行,扫描整个堆中的对象图找出要回收的对象。此过程进行可达性分析,速度很慢。
3、最终标记:Stop The World,处理并发标记时产生的引用变动,使用多条标记线程并发执行。
4、筛选回收:回收废弃对象,此时也要 Stop The World,并使用多条筛选回收线程并发执行。
CMS与G1对比
G1能指定最大停顿时间,G1不会产生内存空间碎片,有利于程序长期执行。
从内存占用来看:由于要维护每个Region的记忆集,G1的卡表需要较大的额外空间,而CMS维护卡表则只需要处理老年代到新生代的引用。
从执行负载的对比:G1采用原始快照搜索算法跟踪并发标记时的引用变化,相比于CMS采用增量更新算法,能减少并发标记和重新标记的消耗,避免CMS在最终标记阶段停顿时间过长的情况。由于G1的卡表比CMS的复杂,所以写屏障操作更复杂,需要消耗更多的运算资源,不能像CMS直接同步操作,而是要利用消息队列。
CMS在小内存应用优于G1,而G1在大内存应用更有优势。