标记-清除算法(Mark-Sweep Algorithm)的 Java 实现
标记-清除算法是垃圾回收(Garbage Collection, GC)中的一种经典算法。它的核心思想是通过两个阶段来回收内存:
-
标记阶段:从根对象(如栈、静态变量等)出发,标记所有可达对象。
-
清除阶段:遍历整个堆内存,回收未被标记的对象(即不可达对象)。
下面我们用 Java 代码来模拟标记-清除算法的流程。
1. 定义对象模型
我们用一个简单的 Object 类来表示堆中的对象,每个对象可以引用其他对象。
class Object {
String name;
Object reference; // 引用其他对象
boolean marked = false; // 标记是否可达
public Object(String name) {
this.name = name;
}
public void setReference(Object reference) {
this.reference = reference;
}
}
2. 模拟堆内存
用一个列表来模拟堆内存,存储所有对象。
import java.util.ArrayList;
import java.util.List;
class Heap {
List<Object> objects = new ArrayList<>();
public void add(Object obj) {
objects.add(obj);
}
public List<Object> getObjects() {
return objects;
}
}
3. 标记阶段
从根对象出发,递归标记所有可达对象。
class Marker {
public void mark(Object obj) {
if (obj == null || obj.marked) {
return;
}
obj.marked = true; // 标记对象为可达
mark(obj.reference); // 递归标记引用的对象
}
}
4. 清除阶段
遍历堆内存,回收未被标记的对象。
class Sweeper {
public void sweep(Heap heap) {
List<Object> objects = heap.getObjects();
for (int i = 0; i < objects.size(); i++) {
Object obj = objects.get(i);
if (!obj.marked) {
System.out.println("Sweeping object: " + obj.name);
objects.remove(i); // 回收对象
i--; // 调整索引
} else {
obj.marked = false; // 重置标记,为下一次 GC 做准备
}
}
}
}
5. 模拟垃圾回收
将上述步骤组合起来,模拟一次完整的垃圾回收。
public class MarkSweepGC {
public static void main(String[] args) {
// 创建堆内存
Heap heap = new Heap();
// 创建对象
Object obj1 = new Object("Object1");
Object obj2 = new Object("Object2");
Object obj3 = new Object("Object3");
Object obj4 = new Object("Object4");
// 设置对象引用关系
obj1.setReference(obj2);
obj2.setReference(obj3);
// obj4 是孤立的,不可达
// 将对象添加到堆中
heap.add(obj1);
heap.add(obj2);
heap.add(obj3);
heap.add(obj4);
// 标记阶段
Marker marker = new Marker();
marker.mark(obj1); // 从根对象 obj1 开始标记
// 清除阶段
Sweeper sweeper = new Sweeper();
sweeper.sweep(heap);
// 打印堆中剩余的对象
System.out.println("Objects in heap after GC:");
for (Object obj : heap.getObjects()) {
System.out.println(obj.name);
}
}
}
代码运行结果
假设堆中有以下对象:
-
obj1->obj2->obj3(可达) -
obj4(不可达)
运行上述代码后,输出如下:
Sweeping object: Object4
Objects in heap after GC:
Object1
Object2
Object3
-
obj4被回收,因为它不可达。 -
obj1、obj2和obj3仍然存在于堆中。
代码解释
-
对象模型:
-
Object类表示堆中的对象,包含一个reference字段指向其他对象。 -
marked字段用于标记对象是否可达。
-
-
堆内存:
-
Heap类模拟堆内存,使用List<Object>存储所有对象。
-
-
标记阶段:
-
从根对象(如
obj1)出发,递归标记所有可达对象。
-
-
清除阶段:
-
遍历堆内存,回收未被标记的对象。
-
重置已标记对象的
marked字段,为下一次 GC 做准备。
-
-
模拟垃圾回收:
-
创建对象并设置引用关系。
-
执行标记和清除阶段,回收不可达对象。
-
标记-清除算法的优缺点
优点:
-
简单直观,容易实现。
-
不需要移动对象,适合处理大对象。
缺点:
-
会产生内存碎片。
-
清除阶段需要遍历整个堆内存,效率较低。
总结
通过上述 Java 代码,我们模拟了标记-清除算法的流程:
-
从根对象出发,标记所有可达对象。
-
遍历堆内存,回收未被标记的对象。
标记-清除算法是垃圾回收的基础算法之一,虽然简单,但在实际应用中可能会产生内存碎片问题。现代垃圾回收器(如 JVM 中的 CMS、G1 等)通常会结合其他算法(如标记-整理、分代回收)来优化性能。

1400

被折叠的 条评论
为什么被折叠?



