垃圾回收器有哪些?它们的区别是什么?代码举例讲解

Java虚拟机常用的垃圾回收器有:

  1. Serial回收器:单线程回收器,会暂停所有的用户线程进行垃圾回收。适用于单CPU环境。
  2. ParNew回收器:多线程回收器,会并行回收新生代的垃圾,用户线程暂停的时间比Serial回收器少。适用于多CPU环境。
  3. Parallel Scavenge回收器:也是新生代多线程回收器,与ParNew相比效率更高, “$” 针对处理器本地化内存分配做了优化。适用于大容量内存环境。
  4. CMS(Concurrent Mark Sweep)回收器:多线程回收器,可与用户线程交替执行,用户线程暂停时间短。适用于对响应时间有要求的场合。
  5. G1(Garbage-First)回收器:最新的多线程、增量式回收器,可替代CMS回收器。

这些垃圾回收器的主要区别有:

  1. 单线程 vs. 多线程:是否会并发执行垃圾回收,影响程序暂停时间。
  2. 新生代 vs. 老年代:主要管理新生代内存还是整个堆内存。
  3. 增量式 vs. 整理式:是增加内存利用率还是防止内存碎片。
  4. 并发 vs. 交替:用户线程是完全暂停还是交替运行。

我们可以通过JVM参数-XX:+UseSerialGC等指定使用的垃圾回收器。也可以不进行指定,虚拟机会根据硬件配置选择默认的最优回收器。

来看一个简单例子,比较Serial和CMS回收器:

public class GCTypeDemo {
    public static void main(String[] args) {
        byte[] data = new byte[1024*1024*10]; // 10MB

        // 设置Serial回收器
        //System.setProperty("java.vm.name", "Serial"); 

        // 设置CMS回收器
        System.setProperty("java.vm.name", "ConcurrentMarkSweepGC");  

        System.out.println("Hello GC!");
    }
}

对该程序使用不同的回收器:

  1. Serial回收器:main方法会暂停几秒钟,执行垃圾回收,然后输出字符串。
  2. CMS回收器:main方法不会暂停,与垃圾回收线程交替执行,几乎不影响程序执行,流畅输出字符串。