JVM目前有五种的垃圾收集器,分别是Serial垃圾收集器、Parallel垃圾收集器,Mostly Concurrent垃圾收集器和Z垃圾收集器。本文将一一介绍这几种垃圾收集器,如果想了解垃圾收集机制内部原理可以参考JVM垃圾收集机制。
Serial垃圾收集器是分代垃圾收集器,它使用单个线程完成垃圾收集工作,当它在工作时,其它所有的线程都会暂停等待垃圾收集工作完成,这种现象就是经常被提到的 Stop the world event,因为它是单线程的,没有多线程之前通信的开销,所以工作效率相对较高,但是同时也没有了多线程的优势,使得它不适合用在多核处理器的机器上。
Serial垃圾收集器在一些特定的环境下会被使用,如果要手动设置使用Serial垃圾收集器,可以通过-XX:+UseSerialGC来启用它。
它优化了垃圾收集器的吞吐量,又被称为Throughput collector(吞吐量收集器),它也是一个分代垃圾收集器,它和Serial垃圾收集器主要的区别就是它是使用多线程去完成垃圾收集工作,而Serial垃圾收集器是使用单线程,如果在多核处理器上,Parallel垃圾收集器利用多线程优势加速完成垃圾收集过程,所以它比较适合用在业务内存使用量较大的多核处理器的机器上。它在进行垃圾收集工作时,同样也会暂停其它所有线程(Stop the world event)直到垃圾收集工作完成。
如果想要手动设置使用Parallel垃圾收集器,可以通过-XX:+UseParallelGC 来启用它,更多配置参考右边的拓展链接👉。
Parallel垃圾收集器和Serial垃圾收集器在新生代和老年代进行垃圾收集时都是会发生Stop the world event,而且持续整个GC过程。
不完全并发垃圾收集器,目前有两个常用的,一个是Concurrent Mark Sweep (CMS) 垃圾收集器和Garbage-First (G1) 垃圾收集器,相对于前面两种垃圾收集器而言,可以减少其它工作线程暂停的时间,但是会消耗较多资源。
CMS垃圾收集器是分代垃圾收集器,它使用多线程进行垃圾收集工作,和Parallel垃圾收集器不同的是,在垃圾收集过程中,CMS垃圾收集器不会总是暂停其它所有线程,大部分时候它的GC线程会和其它工作线程并发执行,优化了垃圾收集的暂停时间,它的一次垃圾收集过程包括以下几个阶段。
其中会造成两次 Stop the world event,一次是在初始标记时,第二次是在再标记时,它的垃圾收集步骤执行顺序图如下。
如果要手动设置使用CMS垃圾收集器,可以通过-XX:+UseParNewGC启用,注:CMS垃圾收集器在Java 9中已经标记废弃deprecated,在Java 14中已经移除。
CMS垃圾收集器在新生代进行垃圾收集时是会发生Stop the world event,而且持续整个GC过程,而在老年代进行垃圾收集时和上面提到过程一致,只有在初始标记时和再标记时才会Stop the world event。
G1垃圾收集器在提高吞吐量和降低垃圾收集的暂停时间方面都做了优化,可以通过参数调节吞吐量和暂停时间的能力以适应不同业务场景,它也是一个分代垃圾收集器,与其它垃圾收集器不同的是,G1是将内存分成了很多固定且大小相等的Region,这些Region被标记成E、S、O、H,分别表示Eden、Survivor、Old、Humongous,其中Humongous表示大对象(内存大于单个Region的50%),不同的分代区在物理内存上是不连续的。
虽然内存在物理上划分方式不同,但是垃圾收集的机制还是和以前的垃圾收集器类似,当Eden区域不够时会触发新生代的垃圾收集,Eden区域的对象会被复制到Survivor区域,Survivor区域的对象年龄达到阈值时,会晋升到Old区域。G1在老年代的垃圾收集过程包括以下几个阶段。
G1垃圾收集器在新生代进行垃圾收集时是会发生Stop the world event,而且持续整个GC过程。
Z Garbage Collector(ZGC)是一个低延迟可扩展的垃圾收集器,它通过Colored Pointers(着色指针)和Load Barrier(读屏障)机制实现了并发转移,大大减少了垃圾收集导致的暂停时间。