AudioInputStream.close()没有正确释放资源,是否有解决方法?

时间:2014-10-23 22:43:31

标签: java audio inputstream ioexception

这是一个关于我观察到的场景的问题:有效关闭由诸如AudioSystems.getAudioInputStream之类的Java库打开的系统资源的方法是什么?我没有可见性和控制权?

请看下面的代码片段:

public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
    System.out.println("Before everthing starts...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
    AudioInputStream stream = AudioSystem.getAudioInputStream(new File("CaptchaResource/silence20ms.wav"));
    System.out.println("After reading in one AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
    stream.close();
    System.out.println("After closing the AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
    stream = AudioSystem.getAudioInputStream(new File("CaptchaResource/silence20ms.wav"));
    System.out.println("After reading in one AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
    stream.close();
    System.out.println("After closing the AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount())
    stream = AudioSystem.getAudioInputStream(new File("CaptchaResource/silence20ms.wav"));
    System.out.println("After reading in one AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
    stream.close();
    System.out.println("After closing the AudioInputStream...Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
}

如您所见,我已使用以下行在程序运行时打印出打开文件描述符的数量:

System.out.println("Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());

这是我观察到的输出:

Before everthing starts...Number of open fd: 4
After reading in one AudioInputStream...Number of open fd: 44
After closing the AudioInputStream...Number of open fd: 43
After reading in one AudioInputStream...Number of open fd: 45
After closing the AudioInputStream...Number of open fd: 44
After reading in one AudioInputStream...Number of open fd: 46
After closing the AudioInputStream...Number of open fd: 45

你可以看到,除了从4到44的第一次跳转之外,每次下次调用getAudioInputStream时,我都会打开另外两个文件描述符。当我在流上调用close()时,我只能关闭一个。

因此,当我的程序必须连续多次处理此操作时,我最终会在Unix系统中达到1024个打开文件描述符限制。

通过查看getAudioInputStream的source code,由于可能存在多个提供程序,我不确定这是否与此方法中打开的多个读者相关,并不确定那里的实现细节。

这听起来像JDK中报告的错误,如下所示:https://bugs.openjdk.java.net/browse/JDK-8013586

这有什么变通方法吗?我怎样才能重写代码以避免这种无法控制的事情发生?

2 个答案:

答案 0 :(得分:4)

好吧我不知道是否有其他人有更好的方法这样做。我现在将自己回答这个问题,因为这是我要使用的解决方法: 在方法结束时调用System.gc()。

不是世界上最伟大的事情。

答案 1 :(得分:2)

旧线程,但如果您从AudioInputStream创建BufferedInputStream,则不会出现此问题。

即,这有效:

FileInputStream fis=new FileInputStream(new File(filePath));
BufferedInputStream bis=new BufferedInputStream(fis);
AudioInputStream stream=AudioSystem.getAudioInputStream(bis);
/*
Some Code
*/
stream.close();
bis.close();
fis.close();

当然,你应该这样做是没有意义的,但它对我有用。

编辑:为了澄清,这使我能够修改filePath指示的文件(即删除,重命名等),这些文件以前不起作用。这可能无法正确完全关闭AudioInputStream(我的一些测试似乎表明不是这样)