This is a question with regard to a scenario I observed: what is the way to effectively close the system resources opened by a Java library like AudioSystems.getAudioInputStream which I do not have visibility and control over?
So take a look at my following code snippet:
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());
}
As you see I've used the following line to print out the number of open file descriptors as program runs:
System.out.println("Number of open fd: " + ((UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getOpenFileDescriptorCount());
And here is the output I observed:
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
You can see that, apart from the first jump from 4 to 44, every next time I call getAudioInputStream I get two more file descriptors opened. While when I call close() on the stream I am only able to close one.
So when my program has to deal with this operation consecutively lots of times and over time, I will eventually hit the 1024 open file descriptor limits in Unix system.
By looking at the source code of getAudioInputStream, I am not sure if this is related to multiple readers were opened inside this method due to the possible existence of multiple providers, not really sure the implementation details there.
And this sounds like it's a reported bug in JDK, as seen in: https://bugs.openjdk.java.net/browse/JDK-8013586
Is there any workarounds on this? How can I rewrite the code to avoid this uncontrollable thing from happening?
Alright I don't know if anyone else has a better way doing this. I will answer this myself for now since this is the workaround I am gonna use: call System.gc() at the end of the method.
Not the greatest thing in the world.