什么是垃圾回收?Java中如何实现垃圾回收?代码举例讲解

垃圾回收(Garbage Collection)是Java的自动内存管理机制,它会自动回收不再使用的对象占用的内存空间,从而防止内存泄漏。

Java中的垃圾回收实现原理如下:

  1. 找出不再使用的对象(垃圾对象)。Java使用引用计数算法来跟踪对象的引用关系,当一个对象的引用数量为0时就认为它是垃圾对象。
  2. 回收垃圾对象占用的内存空间。通过调用该对象的finalize()方法,然后从内存中移除它。
  3. 垃圾收集器会在内存不足时启动,所以对象的回收是不确定的。我们无法知道对象会在什么时候被标记为垃圾对象。

Java提供了几种常用的垃圾收集器:

  • 串行收集器(Serial Collector):单线程收集器,会暂停所有的用户线程进行回收。
  • 并行收集器(Parallel Collector):多线程收集器,也会暂停用户线程,但由多个线程一起进行回收以提高效率。
  • CMS收集器(Concurrent Mark Sweep):并发收集器,用户线程和收集器线程同时执行,不需要完全暂停用户线程。
  • G1收集器(Garbage First):并发收集器,也可以与用户线程同时执行,分代收集,将堆内存划分为不同的区域然后优先回收那些存活对象较少的区域。

来看一个简单例子:
我们可以编写一个Java程序,使用VisualVM观察垃圾收集的过程。

public class GCDemo {
    public static void main(String[] args) {
        GC.gc(); // 手动触发GC

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

        // 回收堆中剩余可用内存,获取内存使用情况
        long used1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 

        buffer = null; // 设置buffer为null,使其成为垃圾对象

        // 再次回收并获取内存使用情况
        long used2 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

        // 两次内存使用之间的差值即为回收的垃圾对象占用的内存
        long gcSize = used1 - used2;

        System.out.println("GC freed " + gcSize + " bytes.");
    }
}

我们可以观察到:

  1. 手动调用GC后,buffer对象仍然存活,内存使用没有变化。
  2. 将buffer置为null后,buffer对象成为垃圾对象。
  3. 第二次GC后,内存使用减少了10MB,这是buffer对象占用的内存被回收了。