Various JRE classes shipped with OpenJDK do not close FileInputStream (and similar) objects when they are finished with them. That means the file descriptors are left open until the garbage collector finalises them.
Most/all of these affect JDK 6, 7 and 8.
It is possible to locate these by using the Byteman script from https://access.redhat.com/knowledge/solutions/233633. Any "finalizing" lines it writes to the "FileInputStream.txt" file indicate a FileDescriptor object which was finalized without having it's close() method explicitly called first.
Searching back through the output file for the object id will in many cases give you the stack trace of what caused the descriptor to be opened, which can lead you to the offending code. The ones I've found so far are by running it against JBoss.
com.sun.naming.internal.ResourceManager.getApplicationResources() opens a number of input streams which it does not close with the lines:
NamingEnumeration<InputStream> resources = helper.getResources(cl, APP_RESOURCE_FILE_NAME);
InputStream istream = helper.getJavaHomeLibStream(JRELIB_PROPERTY_FILE_NAME);
I've created an OpenJDK bug for this, and am waiting for it to be public before posting the link here. The fix for the getJavaHomeLibStream case is trivial, closing it in a finally block.
The fix for getResources() is more complicated since if an exception is thrown, since to close all potential streams, it would need to continue to read from the enumeration closing them all. The actual implementation behind the helper does not open the stream until it's read from the enumeration however.
java.util.jar.Manifest's constructor takes an input stream which it passed to read(). It is not clear from the JavaDoc whether the caller or Manifest itself is responsible for closing the passed input stream.
Since read() wraps the passed one in a FastInputStream which does buffering, the caller can't rely on the state of the InputStream after the constuctor/read call finishes. Manifest doesn't close the stream itself however.
If Manifest should close it, it should be changed to do so. If it shouldn't close it, then I'll file a JBoss Modules bug.
These bugs are generally not critical, since the file descriptors are closed, just not as soon as they can be. The only situation where they may cause problems is if they are called repeatedly, and it causes the file descriptor limit to be hit before the ones that are garbage are finalised.
Hi James -- Does the patch you have cover only part of the fix (getJavaHomeLibStream) or does it also address getResources())?
I've attached the patch to the IcedTea bug, but can post it here too if you want.
No, that's fine.
The patch is in OpenJDK8:
However, Oracle would prefer it was updated to use try-with-resources.
Fixed in 2.4.0: http://blog.fuseyism.com/index.php/2013/06/10/icedtea-2-4-0-released/
Jiri, please update when 2.4.x is available in RHEL 6.x.
We are currently using 2.4.1. Marking closed.