实例可以在其成员暴露于外部世界时进行垃圾收集

时间:2013-03-14 06:59:00

标签: java

采取以下案例

// class Toy {
//     public Object b = new Object();
// }

Toy toy = new Toy();
Object theB = toy.b;
toy = null;

// Can toy instance be garbage collected right now?

我认为可能无法对toy进行垃圾回收,因为theB目前指的是toy.b,变量b无法生效toy(As { {1}}是b)的实例成员变量?

2 个答案:

答案 0 :(得分:3)

回答

是的,它可以,因为Toy的实例没有强引用。想一想:你怎么能回顾原来的Toy实例?不可能,不是吗?因此,它确实是垃圾,并将被收集。

有关Java中可访问性类型的引用的更多信息(即,强引用弱引用 em>等,以及这些引用如何与垃圾收集器交互),看看excellent documentation of the package java.lang.ref


更完整,事情不是那么简单答案

为了进一步扩展讨论,并且绝对准确,我可以想到至少有一种情况,即使在Toy之后,toy = null的实例永远无法收集,类Toy的代码不同。

如果Toy类的构造函数在某种全局变量中添加对新创建的实例的引用(或者更确切地说,如果可以从GC根目录强烈访问该对象)。例如:

public class Toy {
  private static final List<Toy> myToys = new ArrayList<>();
  public Toy() { myToyw.add(this); }
}

如果是这种情况,那么当您在代码中执行toy = null时,实例仍然无法仅仅因为仍然有办法到达它(通过强引用),即Toy.myToys.get(0)

但是,这只是为了完整性。 我强烈建议反对此类代码,因为它肯定会带来很多麻烦,包括但不限于奇怪的内存泄漏(即,实例无法进行GCed )和多线程的问题(即,您在构造函数返回之前发布了对实例的引用,然后另一个线程可能会将对象视为部分初始化,即可能处于不一致状态)。

答案 1 :(得分:0)

是的,如果没有人提及toy,可以对其进行垃圾回收。 b类型为Object后,它仅引用自己的Class对象,而不会引用任何其他内容,因此toy不会引用b