Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 匿名类构造函数中对最终对象的引用是否泄漏?_Java_Android_Memory Leaks_Anonymous Class - Fatal编程技术网

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

Java 匿名类构造函数中对最终对象的引用是否泄漏?,java,android,memory-leaks,anonymous-class,Java,Android,Memory Leaks,Anonymous Class,我正在将runnable传递给服务。可运行的持续时间可能超过传递它的片段/活动。我想知道下面的代码片段是否会通过在runnable中维护引用而泄漏frag对象?我意识到我可以将包含frag的整行代码移到runnable之外(就像我对“String key=frag…”所做的那样),但我只是想了解匿名类如何/何时泄漏对象 我真的不确定。runnable只需要frag在初始化实例时确定一个变量,它在这里是在线初始化的。因此,从理论上讲,在创建内嵌实例之后,它不需要对frag进行任何引用 如果我在ru

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

我真的不确定。runnable只需要frag在初始化实例时确定一个变量,它在这里是在线初始化的。因此,从理论上讲,在创建内嵌实例之后,它不需要对frag进行任何引用

如果我在run()函数中引用了frag,我认为泄漏是可以保证的,因为它需要让frag保持活动状态,以便在将来某个时候引用它(此时frag很可能是gc'd,但用于引用)


我不确定我是否正确理解您使用的单词inline,但无论如何,我不认为这里有任何泄漏

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

Runnable
匿名内部类在
Runnable
线程有效期内可能仍然持有引用(同样,不是指向
frag
,而是指向其中的某个子属性)。(更准确地说,编译器实际上生成了
可运行的
实现
,其中包含一个构造函数和
final
成员变量,这些变量将所有隐式使用的引用复制到
fg_downloadFile()
范围内的任何可用引用。)

但在任何情况下,一旦执行了all代码,对frag的(子成员)的所有引用都将被删除,垃圾收集器可以捡起垃圾


希望这有帮助。

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

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


随着垃圾收集的工作,一旦对象不再被引用,它将接受垃圾收集和释放

如您所知,在匿名类中使用变量时,在外部声明变量时,必须使变量为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

我意识到(几乎)gc语言中的所有内存泄漏都不太符合正常内存泄漏的定义。这里我担心的是,在文件下载之前,服务会一直保持片段的活动状态……任务可能会在队列中等待一段时间,例如,等待启用wifi。我猜术语“正常内存泄漏”与您使用的编程环境有关。是的,碎片肯定会有一段时间是活的。还有其他一些因素导致这种不受欢迎的大内存使用等吗?我知道frag不会在“key=frag”行中泄漏,我想知道的是serviceContext=frag行,它在runnable中。我们是否都同意,如果我在runnable的run()函数中引用frag,那么肯定是泄漏?如果构造函数被视为任何旧函数,那么通过类比,它会泄漏…我们必须假设构造函数不是任何旧函数,编译器非常聪明,知道匿名函数的构造函数只需要一次,这样它就可以在初始化实例后丢弃frag引用。我同意
Runnable
中的引用将在
fg\u downloadFile()
完成后保留,但这不是泄漏。正如下面@seelenvirtuose所表示的,一旦
Runnable
被清理,GC最终将清理所有对象。在
Runnable
“instance”中包含隐式成员的全部目的是确保引用对象的活动时间与
run()
函数中发生的任何事件一致。这和C++中调用的内容很接近。我意识到,你依赖的是内存泄漏的定义,java中没有任何东西是泄漏的。我关心的实际上是服务使片段保持活动的时间,因为任务可能无限期地位于服务中(例如等待wifi)。在java/android中,leak经常被用来指代“保留引用从而阻止GC收集它”。在这种情况下,问题不在于java或runnable中的引用,而在于(池)引用的生存期。在任何情况下,如果您的run函数不需要(隐式)传递到runnable中的所有信息,只需确保它没有被传递。不要给你不需要的东西。无论如何,我看不出有没有
final
和它有什么关系
String key
Context context
File file
Drive drive