JVM标记压缩清除算法是一种垃圾回收算法,用于回收堆内存中不再使用的对象。它的工作流程如下:

  1. 垃圾回收器首先标记所有活动对象,将它们标记为“存活”状态。
  2. 然后,回收器将所有的存活对象压缩到堆的一端,使它们连续排列。
  3. 最后,回收器将堆的另一端标记为“可用”状态,以便将来分配新的对象。 这种算法的优点是可以在压缩阶段减少堆内存的碎片化,提高内存的利用率。但是它的缺点是需要在标记和压缩阶段进行大量的对象移动操作,可能会导致较长的停顿时间。 以下是一个简单的Java示例代码,演示了标记压缩清除算法的工作原理:
javaCopy codepublic class Object {
    private Object reference;
    
    public Object(Object reference) {
        this.reference = reference;
    }
}
public class Main {
    public static void main(String[] args) {
        Object obj1 = new Object(null);
        Object obj2 = new Object(null);
        Object obj3 = new Object(null);
        
        obj1.reference = obj2;
        obj2.reference = obj3;
        obj3.reference = obj1;
        
        obj1 = null;
        obj2 = null;
        obj3 = null;
        
        // 执行垃圾回收
        System.gc();
    }
}

在上面的示例中,创建了三个对象obj1、obj2和obj3,并且通过相互之间的引用建立了一个环。当将这些对象设置为null后,它们将成为不再使用的对象,可以被垃圾回收器回收。执行System.gc()时,会触发垃圾回收器执行标记压缩清除算法,回收这些不再使用的对象。

引用计数法(Reference Counting)

引用计数法是一种垃圾回收算法,用于跟踪对象的引用数量。每当对象被引用时,引用计数加一;当对象的引用被释放时,引用计数减一。当引用计数为零时,表示该对象不再被引用,可以被回收。 引用计数法的优点是实时性较好,可以及时回收不再使用的对象。缺点是无法解决循环引用的问题,即如果两个或多个对象之间互相引用,但与其他对象之间没有引用关系,那么它们的引用计数永远不会为零,导致无法回收这些对象的内存。 以下是一个简单的Java示例代码,演示了引用计数法的工作原理:

javaCopy codepublic class Object {
    private int referenceCount;
    
    public Object() {
        referenceCount = 0;
    }
    
    public void addReference() {
        referenceCount++;
    }
    
    public void releaseReference() {
        referenceCount--;
    }
    
    public int getReferenceCount() {
        return referenceCount;
    }
}
public class Main {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        
        obj1.addReference();
        obj2.addReference();
        obj2.releaseReference();
        
        if (obj1.getReferenceCount() == 0) {
            // obj1可以被回收
        }
        
        if (obj2.getReferenceCount() == 0) {
            // obj2可以被回收
        }
    }
}

在上面的示例中,创建了两个对象obj1和obj2,并通过addReference()方法增加引用计数,通过releaseReference()方法释放引用。当某个对象的引用计数为零时,表示该对象不再被引用,可以被回收。 需要注意的是,引用计数法只能处理直接引用,无法处理循环引用的情况。如果存在循环引用,即使这些对象不再被其他对象直接引用,它们的引用计数仍然不会为零,无法被回收。因此,在实际开发中,很少使用引用计数法作为主要的垃圾回收算法。