-
Bug
-
Resolution: Fixed
-
P4
-
8u11, 9
-
b46
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8084105 | emb-9 | Chris Hegarty | P4 | Resolved | Fixed | team |
A DESCRIPTION OF THE PROBLEM :
The change for Bug ID 7015589 included a change to FilterOutputStream so that it does not swallow exceptions when calling flush:
http://hg.openjdk.java.net/hsx/hotspot-rt/jdk/rev/759aa847dcaf
public void close() throws IOException {
try (OutputStream ostream = out) {
flush();
}
}
The problem is that if close() is called a second time, flush() will be called on the underlying stream after it has already been closed. Many underlying streams will throw an exception in this case.
The implementation of FilterOutputStream.close() should be changed so that it follows the contract of Closeable:
"Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect."
One possible implementation idea is to introduce a member variable to track whether the stream has already been closed:
public void close() throws IOException {
if (!closed) {
closed = true;
try (OutputStream ostream = out) {
flush();
}
}
}
See http://stackoverflow.com/questions/25175882/java-8-filteroutputstream-exception/
REGRESSION. Last worked in version 7u67
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test program
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception is thrown
ACTUAL -
Exception is thrown:
Exception in thread "main" java.io.IOException: Stream closed
at FilterOutputStreamTest$MockBlobOutputStream.flush(FilterOutputStreamTest.java:24)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:141)
at java.io.FilterOutputStream.close(FilterOutputStream.java:158)
at FilterOutputStreamTest.main(FilterOutputStreamTest.java:52)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
public class FilterOutputStreamTest
{
/**
* This stream simulates a OracleBlobOutputStream which will throw
* an exception if flush is called after close.
*/
static class MockBlobOutputStream extends ByteArrayOutputStream
{
private boolean closed;
@Override
public void flush() throws IOException
{
if (closed) {
throw new IOException("Stream closed");
}
}
@Override
public void close() throws IOException
{
closed = true;
}
}
public static void main( final String[] args ) throws Exception
{
try( InputStream bis = new ByteArrayInputStream( "Hello".getBytes() );
OutputStream outStream = new MockBlobOutputStream();
BufferedOutputStream bos = new BufferedOutputStream( outStream );
DeflaterOutputStream deflaterStream = new DeflaterOutputStream(
bos, new Deflater( 3 ) ) )
{
int len = 0;
final byte[] buf = new byte[1024];
while ((len = bis.read(buf)) >= 0)
{
if ( len > 0 )
{
deflaterStream.write(buf,0,len);
}
}
}
}
}
---------- END SOURCE ----------
- backported by
-
JDK-8084105 FilterOutputStream.close may throw IOException if called twice and underlying flush or close fails
- Resolved
- duplicates
-
JDK-8137007 Backport Request : 8054565
- Closed
-
JDK-8065890 Two calls of close method on an output stream cause errors with some VFS (JimFS)
- Closed
- relates to
-
JDK-8078891 java.io.SequenceInputStream.close is not atomic and not idempotent
- Resolved
-
JDK-7015589 (spec) BufferedWriter.close leaves stream open if close of underlying Writer fails
- Closed
-
JDK-8065890 Two calls of close method on an output stream cause errors with some VFS (JimFS)
- Closed
-
JDK-8185092 Data race in FilterOutputStream.close
- Closed
-
JDK-8137007 Backport Request : 8054565
- Closed