垃圾回收的算法有哪些?它们的优缺点是什么?代码举例讲解

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

  1. 标记清除算法:两步操作,首先标记所有可达对象,然后清除所有未标记对象。优点是实现简单,缺点是会产生大量内存碎片。
  2. 复制算法:将内存分为两半,每次只使用其中一半。当一半内存用满了,将还存活的对象复制到另一半内存上,然后清理已使用的内存。优点是没有内存碎片,缺点是只使用一半的内存。
  3. 标记整理算法:与标记清除算法相似,但在清除未标记对象之后会对存活对象进行整理,使得存活对象在内存中变得更加连续。优点是没有内存碎片且内存利用率高,缺点是成本较高。
  4. 标记压缩算法:与标记清除算法和标记整理算法类似,会对存活对象压缩,使存活对象在更加连续的内存空间里。优点是没有内存碎片且内存利用率高,而且内存碎片较少。缺点是成本高,压缩需要的 CPU 成本也很高。

这些垃圾回收算法都采用”可达性分析”来判断对象是否存活。主要区别在于对内存的管理方式不同,有的会产生内存碎片,有的会更充分利用内存,有的需要更长的清理时间等。

来看一个简单例子,比较标记清除算法和标记压缩算法:

public class GCAlgorithmDemo {
    public static void main(String[] args) {
        // 设置标记清除算法
        System.setProperty("java.vm.name", "MarkSweep");  

        byte[] data = new byte[1024*1024*10]; // 10MB

        // 设置标记压缩算法
        System.setProperty("java.vm.name", "MarkCompact");

        byte[] data = new byte[1024*1024*10]; // 10MB
    }
}

对该程序使用不同的垃圾回收算法:

  1. 标记清除算法:执行GC后会产生大量空闲内存,内存利用率降低。
  2. 标记压缩算法:执行GC后内存会被压缩,空闲内存较少,内存利用率高。