本文介绍了垃圾收集无效的FileDescriptor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Android上使用FileDescriptor的开放的资产。看来,垃圾收集改变的FileDescriptor的内部描述为-1。尝试使用数据的FileDescriptor抛出异常后。

I'm opening an asset using a FileDescriptor on Android. It appears that garbage collection changes the FileDescriptor's internal descriptor to -1. Attempting to use the FileDescriptor after that throws an exception.

作为一个全面的检查,我添加了这个$​​ C $ C到空白的项目:

As a sanity check, I added this code to a blank project:

    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的,无需担心争分夺秒垃圾收集器?

Why does this happen? How can I safely use a FileDescriptor without worrying about racing against the garbage collector?

推荐答案

您不能保留在 AssetFileDescriptor 创建openFd的引用( )。当它被GC'ed,它内部有一个 ParcelFileDescriptor ,它也最终GC'ed。这反过来,有参考的FileDescriptor ,你是在调用检索到 getFileDescriptor()。这也恰好有一个完成()方法,调用它时,将关闭该文件描述(通过调用 IoUtils.closeQuietly(MFD); )。这完成()方法将被GC上的 ParcelFileDescriptor 收集时调用。这就是你所观察的行为是如何发生的。

You aren't retaining a reference to the AssetFileDescriptor created by openFd(). When it gets GC'ed, it has an internal ParcelFileDescriptor that is also eventually GC'ed. That, in turn, has the reference to the FileDescriptor that you are retrieving in the call to getFileDescriptor(). It also happens to have a finalize() method that, when called, will close the file descriptor (by calling IoUtils.closeQuietly(mFd);). This finalize() method will be called by the GC when the ParcelFileDescriptor is collected. This is how the behavior you are observing happens.

我的,为什么睡觉不引发这些事件的猜测是,有一个在GC清理东西没有pressure。

My guess as to why sleeping doesn't trigger these events is that there's no pressure on the GC to clean things up.

要测试这个(如果我是对的,到prevent失效),维持了由返回的对象openFd()参考实验持续时间。

To test this (and, if I'm right, to prevent the invalidation), maintain a reference to the object returned by openFd() for the duration of your experiment.

这篇关于垃圾收集无效的FileDescriptor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 23:37