执行 m1 = null;
m2 = null;
后我很困惑。有多少对象有资格进行垃圾回收?
public class MyTest {
MyTest m;
void show() {
System.out.println("Hello this is show method.");
}
public static void main(String args[]) {
MyTest m1 = new MyTest();
MyTest m2 = new MyTest();
MyTest m3 = new MyTest();
m1.m = m2;
m2.m = m3;
m3.m = m1;
m1 = null;
m2 = null;
// Question here: How many objects will be eligible for garbage collection?
}
}
零。
对象引用图如下所示:
https://i.stack.imgur.com/gcJai.png
可以看到引用是循环的。从 main
到 m3
的引用使 m3
对象保持活动状态。反过来,m3
使 m1
保持活动状态,从而使 m2
远离 GC。
请注意,如果您将 m3
设置为 null
,则所有三个对象都将同时符合 GC 条件,尽管每个对象都存在循环引用。 GC 足够聪明,可以确定所有引用都来自符合 GC 条件的对象,并收集所有三个。
可能所有 3 个。 //
标记后没有引用任何变量,因此优化器此时有权将它们从框架中删除。
瞧! GC 不会在这里收集任何东西!让我们看看这里到底发生了什么。当您创建 MyTest
的 m1
、m2
和 m3
三个对象时,对象的创建如下所示(假设对象引用 id 从 410 开始):
m1 MyTest (id=410)
m null
m2 MyTest (id=412)
m null
m3 MyTest (id=414)
m null
当你初始化
m1.m = m2;
m2.m = m3;
m3.m = m1;
对象现在看起来像:
m1 MyTest (id=410)
m MyTest (id=412)
m2 MyTest (id=412)
m MyTest (id=414)
m3 MyTest (id=414)
m MyTest (id=410)
m MyTest (id=412)
m MyTest (id=414)
m MyTest (id=410)
.
.
. (This is circular)
但是在将 m1
和 m2
重新初始化为 null
后,对象如下所示:
m1 null
m2 null
m3 MyTest (id=414)
m MyTest (id=410)
m MyTest (id=412)
m MyTest (id=414)
m MyTest (id=410)
.
.
.
看,m1
和 m2
现在是 null
,但它们的引用在 m3
中仍然存在!
无,因为它们仍然可以通过您通过 m3
在那里构建的循环引用访问