JVM标记压缩清除算法是一种垃圾回收算法,用于回收堆内存中不再使用的对象。它的工作流程如下:
- 垃圾回收器首先标记所有活动对象,将它们标记为“存活”状态。
- 然后,回收器将所有的存活对象压缩到堆的一端,使它们连续排列。
- 最后,回收器将堆的另一端标记为“可用”状态,以便将来分配新的对象。 这种算法的优点是可以在压缩阶段减少堆内存的碎片化,提高内存的利用率。但是它的缺点是需要在标记和压缩阶段进行大量的对象移动操作,可能会导致较长的停顿时间。 以下是一个简单的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()
方法释放引用。当某个对象的引用计数为零时,表示该对象不再被引用,可以被回收。
需要注意的是,引用计数法只能处理直接引用,无法处理循环引用的情况。如果存在循环引用,即使这些对象不再被其他对象直接引用,它们的引用计数仍然不会为零,无法被回收。因此,在实际开发中,很少使用引用计数法作为主要的垃圾回收算法。