我已经毫无疑问地使用final
关键字多年来表示在实例/类的生命周期内不应更改的字段。突然间,这发生在我身上......
所以给出了这个例子:
public class TestFinalGC{
private TestFinalGC(){}
private final Object obj = new Object();
public static void main(String []args){
TestFinalGC instance = new TestFinalGC();
// instance Ref -> actual instance ->? obj ref-> actual obj
System.out.println(instance.obj);
instance = null;
//say GC makes sweep here... what happens?
//lets assume theres more code, obj would obviously be eligible for GC on app exit.
}
}
obj
成员如何在此处泄露? final
字段是否自动WeakReferences,以便如果对父项的强引用为空,它们是否有资格进行垃圾回收?
The JLS does not seem to note anything special about final
更新
因此,我的这个问题建立在“可达性”和强/弱参考密切相关的前提之上。有this confusing oracle doc on reachability让我相信嵌套引用应始终“强烈可达”。因此,我在所有对象中都取消了嵌套对象引用,但看起来显然不应该是我收到的所有注释的情况。
那么关于“可达性”,那么,如果不再能够访问父引用,那么仅仅是嵌套对象引用不再被认为是“可达”的吗?
可能确实是这个问题的前提是不正确的,但仍有一些有趣的信息要合并到这里。
答案 0 :(得分:2)
正如Makoto所建议的那样,就GC而言,变量声明中final
没有什么特别之处。在您的示例代码中
private final Object obj = new Object();
将与
同时进行垃圾收集private Object obj = new Object();
两者都是强引用,但是无效并且与其父类TestFinalGC
实例一起收集垃圾。这是因为当实例是GC'd时,参考字段也会被销毁,并且引用不再存在。 obj的引用计数因此减少了一个。
但是,你应该写一些像
这样的东西Object x = myTestFinalGC.obj; // only works if your obj is not private, of course
然后该对象将不会被垃圾收集,因为它仍然会有一个引用延迟(假设这个特定的代码行在另一个类实例中,当myTestFinalGC被垃圾收集时仍保持活动状态。
tl; dr:内存分配在硬引用计数降为零时收集垃圾(当然收集器运行)。 final
并未改变这一事实。