Java垃圾可以在范围结束前收集变量吗?

时间:2016-09-02 05:47:30

标签: java reference garbage-collection weak-references

假设我们有这样的程序:

void main() {
    // Point 0
    BigThing bt = new BigThing();
    // Point 1
    WeakReference<BigThing> weak = new WeakReference<>(bt);
    // Point 2
    doSomething(weak);
    // Point 3
}

void doSomething(...) { ... }

我们知道,对BigThing对象的弱引用无法阻止对象在不再强烈可达时被垃圾回收。

我的问题是关于局部变量bt,它是对BigThing对象的强引用。 对象在第2点(在调用doSomething()之前)或第3点(块范围结束)之间是否变得不可达?

这个问题的答案将影响对doSomething()的调用是否能够保证能够访问实时BigThing对象,或者在函数调用期间底层对象是否会死亡。

我不确定,因为你可以争辩说,在第2点之后,局部变量bt永远不会被读或写,所以变量实际上已经死了,指针值可以被丢弃。如果所有引用都很强,这种“优化”将是有效的,但是当引入软,弱和幻像引用的概念以及终结器时,推理就会分崩离析。同样作为类比,因为C ++具有析构函数,所以必须在作用域的末尾销毁一个值,并且不能将其移动到最后一次使用的位置。

2 个答案:

答案 0 :(得分:3)

我想说这个对象可以在第2点收集,在JLS section 12.6.1中使用以下语言:

  

可以设计优化程序的转换,以减少可达到的对象数量,使其少于可以被认为可达的对象数量。例如, Java编译器或代码生成器可以选择设置一个不再用于null 的变量或参数,以使此类对象的存储可能更快地回收。

由于在{2}之后将不再使用bt变量,因此Java可以自由清除该变量,从而使BigThing对象只能微弱地到达。

答案 1 :(得分:2)

Java 9引入Reference.reachabilityFence来解决这种情况,这当然也意味着它确实存在于第一位。