Appearance
什么是三色标记
三色标记法是一种用于垃圾回收算法中的对象标记方法,特别用于标记-清除型垃圾回收器。这种方法通过使用三种颜色(白色、灰色和黑色)来跟踪对象的可达性和垃圾回收状态,以避免对象的重复回收和丢失。
三色标记的基本概念
- 白色:表示对象尚未被检查。白色对象可能是垃圾,直到证明它们是可达的。
- 灰色:表示对象被检查过,并且其本身是可达的,但其引用的对象还未全部检查。
- 黑色:表示对象和它所有引用的对象都已检查且是可达的。
三色标记步骤
- 初始化:所有对象开始时都是白色。
- 标记开始:从GC Roots开始,根对象标记为灰色。
- 扫描灰色对象:
- 将灰色对象引用的所有白色对象标记为灰色。
- 然后将该灰色对象标记为黑色。
- 重复步骤3直到没有更多的灰色对象。
- 清除:未标记为黑色的对象为白色,即垃圾,可被回收。
代码示例模拟
以下是一个简单的模拟示例,展示了假设某个对象图的三色标记流程:
java
import java.util.HashSet;
import java.util.Set;
class ObjectNode {
String name;
Set<ObjectNode> references = new HashSet<>();
String color = "White"; // White by default
ObjectNode(String name) {
this.name = name;
}
void addReference(ObjectNode node) {
references.add(node);
}
@Override
public String toString() {
return name;
}
}
public class TricolorMarkingExample {
private static Set<ObjectNode> roots = new HashSet<>();
public static void main(String[] args) {
// Create objects
ObjectNode objA = new ObjectNode("A");
ObjectNode objB = new ObjectNode("B");
ObjectNode objC = new ObjectNode("C");
// Create references
objA.addReference(objB);
objB.addReference(objC);
// GC Roots
roots.add(objA);
roots.add(objB);
// Perform tricolor marking
performTricolorMarking();
}
static void performTricolorMarking() {
// Initial marking of root nodes
for (ObjectNode root : roots) {
markGray(root);
}
while (roots.stream().anyMatch(node -> node.color.equals("Gray"))) {
for (ObjectNode root : roots) {
if (root.color.equals("Gray")) {
scanAndBlacken(root);
}
}
}
// Output the color result
System.out.println("Final color states:");
roots.forEach(root -> System.out.println(root.name + ": " + root.color + ", references: " + root.references));
}
static void markGray(ObjectNode node) {
if (node.color.equals("White")) {
System.out.println("Marking " + node.name + " gray.");
node.color = "Gray";
}
}
static void scanAndBlacken(ObjectNode node) {
System.out.println("Scanning and blackening " + node.name);
node.references.forEach(reference -> {
if (reference.color.equals("White")) {
markGray(reference);
}
});
node.color = "Black";
}
}解释
- 对象生成:创建若干对象并引用它们。
- 根集合:设定起始对象集,通常指代程序运行时栈、全局引用等。
- 三色规则应用:通过
markGray和scanAndBlacken函数演示从GC Roots开始的标记过程。 - 最终输出:显示对象的颜色状态和引用关系,以验证三色标记的正确性。
使用三色标记的好处
- 避免循环引用:能够正确识别循环引用对象不被误判为不可回收。
- 并发性增强:支持并发标记,减少“Stop-the-World”时间。
- 渐进性:可以执行增量垃圾回收,减小程序暂停。
在实际的垃圾回收算法实现中,如G1和CMS,三色标记法被广泛应用,用于高效地管理内存和提高程序运行的性能。
更新: 2024-08-09 15:59:48
原文: https://www.yuque.com/tulingzhouyu/db22bv/sguahv8u1s2tckek
短视频
最近有一位工作 3 年的粉丝,在后台留言 面试的时候被问到什么是三色标记法?当时一脸懵逼,天天 CRUD,三色标记是什么鬼啊。
其实三色标记法是Java虚拟机中一种用于垃圾回收的算法,主要是用于标记内存中的对象,好确定哪些对象是存活的,哪些对象是可以被回收的。
这种算法将内存中的对象分为三种颜色:白色 黑色 灰色
白色代表对象还没被扫描过,我们可以理解为是未知状态。
黑色代表对象已经被扫描过,但是 它的引用对象还没被有扫描过。
灰色代表对象已经被扫描过了, 并且它的引用对象也全都被扫描过了,我们可以理解为是已知状态。
在GC开始的时候会将所有对象都标记为白色。
然后从根对象开始遍历内存中的对象,遍历过程中它会把直接引用对象都标记为灰色,并且把它们加入到灰色集合中。
接着呢,会逐个判断灰色集合中的对象是否存在子对象
如果存在就继续放入灰色集合中,如果不存在就标记为黑色,放入到黑色集合中。
然后重复这个过程,直到灰色集合处理为空,也就代表这一轮标记就完成了。
最终,所有存活的对象都会被标记为黑色,而未被标记的白色对象就是待回收的垃圾对象。
而垃圾回收器通过三色标记算法 在一定程度上减少了** gc 停顿时间**,提高了系统的性能和响应速度。
以上就是我对三色标记法的理解。
更新: 2024-05-15 14:13:11
原文: https://www.yuque.com/tulingzhouyu/db22bv/xnnlrqaa80pnu0zn