Nathan, thanks a lot for reporting this. Sorry no one has replied to you 
earlier, 
but your bug report was actually entered into the JBS (JDK Bug System):

        https://bugs.openjdk.java.net/browse/JDK-8054565

So don't worry, it won't get lost.
Now about the issue itself. It's indeed a bug. Though methods should be written 
in
an atomic fashion [1] (where possible and where it makes sense), you are right 
--
java.io.Closeable#close is certainly not one of these methods.
There is nothing you can do if 'close' fails. This method has a terminal 
semantics.
Implementations cannot rely on some external retry strategy. 
java.io.Closeable#close
should be called at most once in a lifetime of a Closeable object.

I skimmed through the JDK sources and found some more examples of this 
behaviour.
They should be fixed as well. As for this particular issue, I see two options:

        1. We just fix it and that's it
        2. You sign OCA [2], provide a test, prepare a change review
           and if everything is fine we push it with comment 
           'Contributed-by: nathan.a.clem...@hotmail.com' (or whatever email 
you choose)

---------------------------------------------------------------------------------
[1] Effective Java, Second Edition, Item 64: Strive for failure atomicity
[2] http://openjdk.java.net/contribute/

-Pavel

> On 2 Dec 2014, at 23:36, Nathan Clement <nathan.a.clem...@hotmail.com> wrote:
> 
> 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
>                                         

Reply via email to