最终字段如何不泄漏内存?

rpg*_*711 6 java garbage-collection memory-leaks final

我已经毫无疑问地使用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.
     }
}
Run Code Online (Sandbox Code Playgroud)

obj会员怎么不泄漏?final字段是否自动WeakReferences,以便如果对父项的强引用为空,它们是否有资格进行垃圾回收?

JLS似乎没有注意到有关final的任何特别之处

更新:

因此,我的这个问题建立在"可达性"和强/弱参考密切相关的前提之上.有关于这个可达性混乱的Oracle文档,导致我相信,嵌套引用应该永远是"强可到达".因此,我在所有对象中都取消了嵌套对象引用,但看起来显然不应该是我收到的所有注释的情况.

那么关于"可达性",那么,如果父引用不再可达,那么仅仅是嵌套对象引用不再被视为"可达"吗?

可能是真的,这个问题的前提是不正确的,但仍然有耐人寻味的信息在这里巩固.

vel*_*lis 3

final正如 Makoto 所说,就 GC 而言,变量声明没有什么特别之处。在你的示例代码中

private final Object obj = new Object();
Run Code Online (Sandbox Code Playgroud)

将同时被垃圾收集

private Object obj = new Object();
Run Code Online (Sandbox Code Playgroud)

两者都是强引用,但会与其父类TestFinalGC实例一起失效并被垃圾回收。这是因为当实例被 GC 时,引用字段也会被销毁,并且引用不再存在。obj 的引用计数因此减一。

但是,你应该写一些像

Object x = myTestFinalGC.obj; // only works if your obj is not private, of course
Run Code Online (Sandbox Code Playgroud)

那么该对象将不会被垃圾收集,因为它仍然有一个引用徘徊(假设这一特定代码行位于另一个类实例中,当 myTestFinalGC 被垃圾收集时,该实例仍然处于活动状态。

tl;dr:当内存分配的硬引用计数降至零(当然,收集器运行)时,内存分配将被垃圾收集。final并没有改变这个事实。