Hi,
I have encountered a bug in FilterOutputStream under Java 8. The bug is that
calling close() on the same stream twice can now result in an exception,
whereas under Java 7 it did not. The reason is that FilterOutputStream.close()
calls flush() before calling close() on the underlying stream. Calling close()
twice on the FilterOutputStream will thus result in flush() being called twice.
Some streams (such as OracleBlobOutputStream) will throw an exception if
flush() is called after the stream is closed. In Java 7 any exceptions when
calling flush() were ignored, but in Java 8 these exceptions are passed on to
the caller.
This bug appears to have been introduced in "7015589: (spec)
BufferedWriter.close leaves stream open if close of underlying Writer fails".
The FilterOutputStream.close() method now does not obey the contract of
AutoClosable.close(): "If the stream is already closed then invoking this
method has no effect."
Some sample code that illustrates the problem:
try( InputStream bis = new BufferedInputStream( inputStream );
OutputStream outStream = payloadData.setBinaryStream( 0 );
BufferedOutputStream bos = new BufferedOutputStream( outStream );
DeflaterOutputStream deflaterStream = new DeflaterOutputStream(
bos, new Deflater( 3 ) ) )
{
fileSize = IOUtil.copy( bis, deflaterStream );
}
The try-with-resources mechanism will call close on the DeflaterOutputStream,
which will in turn call close on the BufferedOutputStream, which will call
flush() then close() on the blob output stream. The try-with-resources
mechanism will then call close on the BufferedOutputStream which again calls
flush() on the blob output stream, resulting in an exception.
My proposed fix is to change FilterOutputStream.close() as follows:
@Override
@SuppressWarnings("try")
public void close() throws IOException {
if (!closed) {
closed = true;
try (OutputStream ostream = out) {
flush();
}
}
}
private boolean closed = false;
This will prevent flush() being called on an already closed stream.
I have reported this issue via the Oracle bug tracker and got Review ID
JI-9014085, however I never received any follow up from Oracle. I have also
discussed the issue on Stack Overflow:
http://stackoverflow.com/questions/25175882/java-8-filteroutputstream-exception.
Do people agree that this is a bug? If so, what is the process for fixing it?
Thanks,
Nathan Clement