Android 垃圾回收使FileDescriptor无效?

Android 垃圾回收使FileDescriptor无效?,android,garbage-collection,file-descriptor,Android,Garbage Collection,File Descriptor,我正在Android上使用FileDescriptor打开一个资产。垃圾回收似乎将FileDescriptor的内部描述符更改为-1。在此之后尝试使用FileDescriptor会引发异常 作为健全性检查,我将以下代码添加到一个空白项目中: try{ fd = getAssets().openFd("greensleeves.wav").getFileDescriptor(); }catch(IOException e) { } System.o

我正在Android上使用FileDescriptor打开一个资产。垃圾回收似乎将FileDescriptor的内部描述符更改为-1。在此之后尝试使用FileDescriptor会引发异常

作为健全性检查,我将以下代码添加到一个空白项目中:

    try{
        fd = getAssets().openFd("greensleeves.wav").getFileDescriptor();
    }catch(IOException e) {
    }

    System.out.println("file descriptor before gc" + fd);
    try { Thread.sleep(100); } catch (InterruptedException e) {}
    System.out.println("file descriptor before gc" + fd);
    try { Thread.sleep(100); } catch (InterruptedException e) {}
    System.out.println("file descriptor before gc" + fd);
    System.gc();
    System.out.println("file descriptor after gc" + fd);
    System.out.println("file descriptor after gc" + fd);
    System.out.println("file descriptor after gc" + fd);
这是输出

      System.out  I  file descriptor before gcFileDescriptor[45]
      System.out  I  file descriptor before gcFileDescriptor[45]
      System.out  I  file descriptor before gcFileDescriptor[45]
        dalvikvm  D  GC_EXPLICIT freed 176K, 3% free 9108K/9316K, paused 2ms+2ms, total 24ms
      System.out  I  file descriptor after gcFileDescriptor[-1]
      System.out  I  file descriptor after gcFileDescriptor[-1]
      System.out  I  file descriptor after gcFileDescriptor[-1]

为什么会发生这种情况?如何安全地使用FileDescriptor而不用担心与垃圾收集器竞争?

您没有保留对
openFd()
创建的
AssetFileDescriptor
的引用。当它得到GC'ed时,它有一个内部的
ParcelFileDescriptor
,它最终也是GC'ed的。反过来,它有对
FileDescriptor
的引用,您正在调用
getFileDescriptor()
中检索该
FileDescriptor
。它还有一个
finalize()
方法,当调用该方法时,它将关闭文件描述符(通过调用
IoUtils.closequity(mFd);
)。收集
ParcelFileDescriptor
时,GC将调用此
finalize()
方法。这就是你观察到的行为发生的方式

至于为什么睡眠不会触发这些事件,我的猜测是GC没有压力来清理这些事情


为了测试这一点(如果我是对的,为了防止无效),请在实验期间保留对
openFd()
返回的对象的引用。

您没有保留对
openFd()
创建的
AssetFileDescriptor
的引用。当它得到GC'ed时,它有一个内部的
ParcelFileDescriptor
,它最终也是GC'ed的。反过来,它有对
FileDescriptor
的引用,您正在调用
getFileDescriptor()
中检索该
FileDescriptor
。它还有一个
finalize()
方法,当调用该方法时,它将关闭文件描述符(通过调用
IoUtils.closequity(mFd);
)。收集
ParcelFileDescriptor
时,GC将调用此
finalize()
方法。这就是你观察到的行为发生的方式

至于为什么睡眠不会触发这些事件,我的猜测是GC没有压力来清理这些事情


为了测试这一点(如果我是对的,为了防止无效),请在实验期间保留对
openFd()
返回的对象的引用。

您没有保留对
openFd()
创建的
AssetFileDescriptor
的引用。当它得到GC'ed时,它有一个内部的
ParcelFileDescriptor
,它最终也是GC'ed的。反过来,它有对
FileDescriptor
的引用,您正在调用
getFileDescriptor()
中检索该
FileDescriptor
。它还有一个
finalize()
方法,当调用该方法时,它将关闭文件描述符(通过调用
IoUtils.closequity(mFd);
)。收集
ParcelFileDescriptor
时,GC将调用此
finalize()
方法。这就是你观察到的行为发生的方式

至于为什么睡眠不会触发这些事件,我的猜测是GC没有压力来清理这些事情


为了测试这一点(如果我是对的,为了防止无效),请在实验期间保留对
openFd()
返回的对象的引用。

您没有保留对
openFd()
创建的
AssetFileDescriptor
的引用。当它得到GC'ed时,它有一个内部的
ParcelFileDescriptor
,它最终也是GC'ed的。反过来,它有对
FileDescriptor
的引用,您正在调用
getFileDescriptor()
中检索该
FileDescriptor
。它还有一个
finalize()
方法,当调用该方法时,它将关闭文件描述符(通过调用
IoUtils.closequity(mFd);
)。收集
ParcelFileDescriptor
时,GC将调用此
finalize()
方法。这就是你观察到的行为发生的方式

至于为什么睡眠不会触发这些事件,我的猜测是GC没有压力来清理这些事情

为了测试这一点(如果我是对的,为了防止无效),请在实验期间维护对
openFd()
返回的对象的引用