为什么以下对象不符合垃圾回收条件?
why the following object is not eligible for garbage collection?
在下面的代码中,我不明白为什么引用b2
创建的对象不是null
??。
因为我通过将 b2 = null
传递给 b1
对象的 go()
方法(在制作 b1 = null
之前)制作了 b2 = null
。
class Demo {
Short story = 200;
Demo go(Demo cb) {
cb = null;
return cb;
}
public static void main(String[] args) {
demo b1 = new demo();
demo b2 = new demo();
demo b3 = b1.go(b2);
b1 = null;
// b1 has been collected by gc hence is null
System.out.println(b1.hashCode());
// b3 is also null
System.out.println(b3.hashCode());
// but how come b2 is not null?
System.out.println(b2.hashCode());
}
}
所以请有人解释一下为什么 b2 没有被垃圾回收,甚至使它为空?
垃圾回收不是这样工作的。垃圾收集器将找到不再有任何引用的对象,并收集它们。它将不会收集仍然引用它们的对象,并且不会将任何变量设置为空。
因为 cb 指向与 b2 相同的对象,但 cb 与 b2 不是同一个变量。将 cb 设置为 null 对 b2 或 b2 指向的对象没有任何作用。
demo b3 = b1.go(b2);
Demo go(Demo cb){
cb = null;
return cb;
}
使用上面的代码,第一个 b2
和 cb
将指向同一个对象。然后,当您执行 cb = null;
然后执行 cb
时,引用将丢失。但是 b2
仍然指向原来的对象。
这意味着至少一个对象 (b2
) 正在主动持有对分配的 memory/object 的引用。它将不符合垃圾收集的条件。
将任何对象设置为 null
引用并不意味着它被垃圾收集器收集。这只是意味着,现在没有对分配对象的活动引用,因此它符合垃圾收集条件。
您首先需要知道垃圾回收 (GC) 与将某些内容设置为 null 不同。
这里我打个比方。变量(b1
、b2
、b3
等)就像 children。而 objects (new Demo()
) 就像气球一样。当你写:
demo b1 = new demo();
你让 child b1
拿着一个新的气球。当您将 b1
设置为 null 时,您让 child 放开了他的气球。气球飞走了,但它仍然存在于天空的某个地方。另一方面,GC 就像一台超级 hi-tech 机器,能够接住这些飞翔的气球。在 child 放开气球后,GC 会在一段时间后注意到它(这个 "time" 可能会有所不同)并去收集它并销毁它。
既然您了解了 nullity 和 GC 之间的区别,我们可以继续解决您的实际问题。在方法
Demo go(Demo cb){
cb = null;
return cb;
}
您正在将 cb 设置为 null 并 returning 它。 return 值为空。但是,cb
不是您之前传入的 child (b2
)。你有一个 child 拿着气球 (b2
),当你 "pass the child in as a parameter",你没有传递 child,你是在邀请另一个 child抓住同一个气球。在该方法中,cb
是另一个 child。所以当设置cb
为null时,你是让"another child"放开气球,但是原来的childb2
还拿着它。
看到了吗? b2还拿着气球呢!他不为空!
在下面的代码中,我不明白为什么引用b2
创建的对象不是null
??。
因为我通过将 b2 = null
传递给 b1
对象的 go()
方法(在制作 b1 = null
之前)制作了 b2 = null
。
class Demo {
Short story = 200;
Demo go(Demo cb) {
cb = null;
return cb;
}
public static void main(String[] args) {
demo b1 = new demo();
demo b2 = new demo();
demo b3 = b1.go(b2);
b1 = null;
// b1 has been collected by gc hence is null
System.out.println(b1.hashCode());
// b3 is also null
System.out.println(b3.hashCode());
// but how come b2 is not null?
System.out.println(b2.hashCode());
}
}
所以请有人解释一下为什么 b2 没有被垃圾回收,甚至使它为空?
垃圾回收不是这样工作的。垃圾收集器将找到不再有任何引用的对象,并收集它们。它将不会收集仍然引用它们的对象,并且不会将任何变量设置为空。
因为 cb 指向与 b2 相同的对象,但 cb 与 b2 不是同一个变量。将 cb 设置为 null 对 b2 或 b2 指向的对象没有任何作用。
demo b3 = b1.go(b2);
Demo go(Demo cb){
cb = null;
return cb;
}
使用上面的代码,第一个 b2
和 cb
将指向同一个对象。然后,当您执行 cb = null;
然后执行 cb
时,引用将丢失。但是 b2
仍然指向原来的对象。
这意味着至少一个对象 (b2
) 正在主动持有对分配的 memory/object 的引用。它将不符合垃圾收集的条件。
将任何对象设置为 null
引用并不意味着它被垃圾收集器收集。这只是意味着,现在没有对分配对象的活动引用,因此它符合垃圾收集条件。
您首先需要知道垃圾回收 (GC) 与将某些内容设置为 null 不同。
这里我打个比方。变量(b1
、b2
、b3
等)就像 children。而 objects (new Demo()
) 就像气球一样。当你写:
demo b1 = new demo();
你让 child b1
拿着一个新的气球。当您将 b1
设置为 null 时,您让 child 放开了他的气球。气球飞走了,但它仍然存在于天空的某个地方。另一方面,GC 就像一台超级 hi-tech 机器,能够接住这些飞翔的气球。在 child 放开气球后,GC 会在一段时间后注意到它(这个 "time" 可能会有所不同)并去收集它并销毁它。
既然您了解了 nullity 和 GC 之间的区别,我们可以继续解决您的实际问题。在方法
Demo go(Demo cb){
cb = null;
return cb;
}
您正在将 cb 设置为 null 并 returning 它。 return 值为空。但是,cb
不是您之前传入的 child (b2
)。你有一个 child 拿着气球 (b2
),当你 "pass the child in as a parameter",你没有传递 child,你是在邀请另一个 child抓住同一个气球。在该方法中,cb
是另一个 child。所以当设置cb
为null时,你是让"another child"放开气球,但是原来的childb2
还拿着它。
看到了吗? b2还拿着气球呢!他不为空!