Java 8 FilterOutputStream exception

This was a method change FilterOutputStream.close()in Java 8, which caused some problems. (See http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/759aa847dcaf )

In previous versions of Java, the following code worked without exception. However, in Java 8, we always get an exception when the try-with-resources mechanism closes threads.

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 first call close()on deflaterStream. Since deflaterStreamwraps boswhich wraps outStream, deflaterStream.close()is bos.close()that calls outStream.close(), which closes the base flow in the database.

The try-with-resources mechanism will then call close()on bos. As it boscontinues FilterOutputStream, it flush()will first be called on outStream. However, since it is outStreamalready closed, it outStream.flush()throws an exception:java.sql.SQLException: Closed LOB

caused by: java.io.IOException: Closed LOB
     at oracle.jdbc.driver.OracleBlobOutputStream.ensureOpen(OracleBlobOutputStream.java:265)
     at oracle.jdbc.driver.OracleBlobOutputStream.flush(OracleBlobOutputStream.java:167)
     at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:141)
     at java.io.FilterOutputStream.close(FilterOutputStream.java:158)
     at com.blah.uploadFile(CustomerUploadFacade.java:162)
     ... 38 more
Caused by: java.sql.SQLException: Closed LOB
     at oracle.jdbc.driver.OracleBlobOutputStream.ensureOpen(OracleBlobOutputStream.java:257)
     ... 42 more

Has anyone else experienced this issue? If so, how did you manage? Is there something wrong with the way we use try-with-resources?

+4
source share
4 answers

This is a mistake in FilterOutputStream. This implements Closable . The contract for this interface reads:

Closes this thread and frees the associated system resources. If the thread is already closed, calling this method has no effect.

.close() , flush(), .

FilterOutputStream , .

, try , FindBugs Eclipse, . , , .

CloseOnceBufferedOutputStream, BufferedOutputStream. boolean, , , . close(), , . , return.

Oracle , , .

+2

bos outStream try, . AutoClosable .

JVM AutoClosable, , . close() , , .

deflaterStream :

try( InputStream bis = new BufferedInputStream( inputStream );
     DeflaterOutputStream deflaterStream = new DeflaterOutputStream(
        new BufferedOutputStream( payloadData.setBinaryStream( 0 ) ),
            new Deflater( 3 ) ) )
{
    fileSize = IOUtil.copy( bis, deflaterStream );
}

Edit:

, , payloadData.setBinaryStream( 0 ), - :

OutputStream outStream = null;
try( InputStream bis = new BufferedInputStream( inputStream );
     DeflaterOutputStream deflaterStream = new DeflaterOutputStream(
        new BufferedOutputStream( outStream = payloadData.setBinaryStream( 0 ) ),
            new Deflater( 3 ) ) )
{
    fileSize = IOUtil.copy( bis, deflaterStream );
}
catch (ExceptionsYouWantToCatch eywtc)
{
    if (outStream != null) {
        // Here you have the chance to close it
        try { outStream.close(); } catch(IOException ie){}
    }
}
+1

, , ...

, , .

try( InputStream bis = new BufferedInputStream( inputStream );
     DeflaterOutputStream deflaterStream = new DeflaterOutputStream(
         new BufferedOutputStream( payloadData.setBinaryStream( 0 ) ), new Deflater( 3 ) ) )
{
    fileSize = IOUtil.copy( bis, blobDeflaterStream );
}

, deflatorStream , .

0
source

Our final solution was to fix FilterOutputStream ourselves:

public void close() throws IOException {
    if (!closed) {
        closed = true;
        try (OutputStream ostream = out) {
            flush();
        }
    }
}

private boolean closed = false;

This class was included in a small JAR file and added to the download path: -Xbootclasspath/p:%APP_HOME%\lib\jdkFix.jar

I hope Oracle recognizes that this problem is a bug and is fixed in a future Java 8 update.

0
source

All Articles