在匿名类构造函数中引用最终对象是否泄漏?

时间:2014-10-31 07:25:23

标签: java android memory-leaks anonymous-class

我正在将runnable传递给服务。可运行的持续时间可能比通过它的片段/活动寿命更长。我想知道以下代码片段是否会通过在runnable中维护引用来泄漏frag对象?我意识到我可以在runnable之外移动包含frag的整行(就像我用“String key = frag ...”所做的那样),但我只是想要了解匿名类如何/何时泄漏对象

我真的不确定。 runnable只需要frag来在初始化实例时确定变量,并在此处进行内联初始化。因此从理论上讲,在创建内联实例后,不需要对frag进行任何引用。

如果我在run()函数中有一个对frag的引用,我认为会保证泄漏,因为它需要保持frag活着以便在将来某个时候引用它(而且frag很可能是gc' d在那一点上,但作为参考)。

private static void fg_downloadFile(final FragMyDrive frag, final File file, final Drive drive){

    final String key = frag.getCastedActivity().getKey();

    Runnable rx_downloadFile = new Runnable() {

        Context ServiceContext = frag.getCastedActivity().mService;

        @Override
        public void run() {

            bg_downloadFile(ServiceContext, key, file, drive);
        }
    }; 

    //.... Submit runnable to service...
}

3 个答案:

答案 0 :(得分:2)

正如您所知,您必须在外部声明变量 final ,但在匿名类中使用它们。这里的Java技巧是将所有这些变量复制到该匿名类的隐式生成的实例字段中。

话虽如此,但这意味着确实存在实例字段(在您的runnable中),其中包含外部作用域的所有访问变量的副本。在您的示例中,当您只是访问它时,它也会引用FragMyDrive

在runnable有资格进行垃圾回收的同时,所有这些对象都有资格进行垃圾回收。这意味着只要它正在运行,对runnable中FragMyDrive的引用就会使该对象保持活动状态。

将这些引用缩小到您真正需要的范围始终是一个好主意:

private static void fg_downloadFile(final FragMyDrive frag, final File file, final Drive drive){
    final String key = frag.getCastedActivity().getKey();
    final Context context = frag.getCastedActivity().mService;

    Runnable rx_downloadFile = new Runnable() {
        @Override
        public void run() {
            bg_downloadFile(context, key, file, drive);
        }
    }; 
    //.... Submit runnable to service...
}

这里唯一(隐式生成的)实例字段是:

String key
Context context
File file
Drive drive

答案 1 :(得分:1)

我不确定我是否理解您正确使用内联这个词,但无论如何,我都不认为这里有任何泄露。

Var final String key只是静态函数fg_downloadFile()中的本地引用,因此在函数末尾超出范围时会释放它。

只要Runnable线程存在,frag匿名内部类仍然可以保持引用(再次,不是Runnable而是其中的某个子属性)。 (更确切地说,编译器实际上使用构造函数和implementation成员变量生成Runnable final个成员变量,将任何隐式使用的引用复制到fg_downloadFile()&#39中可用的任何内容;范围。)

但无论如何,一旦所有代码都被执行,所有对frag的(子成员)的引用都将被删除,垃圾收集器可以拾取垃圾。

希望这有帮助。

答案 2 :(得分:0)

有趣的问题。你有没有自动垃圾收集的编程经验,比如Objective C?

但是要回答你的问题,我不明白为什么会出现泄漏。 我想会发生的事情是Runnable会保留对frag的引用以供它自己使用,但是在将来的某个时候,一旦服务不再需要它,frag也会被垃圾收集,因此它不会引用它

当垃圾收集工作时,一旦不再引用对象,它将被垃圾收集和解除分配。