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

Nay*_*uki 5 java garbage-collection reference 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(...) { ... }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

use*_*ica 5

我想说该对象在第 2 点是可收集的,按照JLS 第 12.6.1 节中的以下语言:

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

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