9

I have this piece of code, which is to write an Ojbect to a byte array stream:

     static byte[] toBytes(MyTokens tokens) throws IOException {
        ByteArrayOutputStream out = null;
        ObjectOutput s = null;
        try {
            out = new ByteArrayOutputStream();
            try {
                s = new ObjectOutputStream(out);
                s.writeObject(tokens);
            } finally {
                try {
                    s.close();
                } catch (Exception e) {
                    throw new CSBRuntimeException(e);
                }             
            }
        } catch (Exception e) {
            throw new CSBRuntimeException(e);
        } finally {
            IOUtils.closeQuietly(out);
        }
        return out.toByteArray();
    }

However, FindBugs keeps complaining about line:

s = new ObjectOutputStream(out);

that "may fail to close stream" - BAD_PRACTICE - OS_OPEN_STREAM. Can somebody help?

pidabrow
  • 966
  • 1
  • 21
  • 47
Eugene
  • 607
  • 3
  • 8
  • 12
  • If you are using Java 7, you can use [try-with-resources](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html). – Duncan Jones Jan 21 '13 at 07:59
  • Unfortunately, I'm stuck with Java 6 – Eugene Jan 21 '13 at 08:08
  • Just FYI - I'm unable to get my FindBugs to complain about your code. I'm using the latest FindBugs Eclipse, with the reporting level set to 20 (the least concerning) and every category enabled. What version of FindBugs are you using and how are you executing it? – Duncan Jones Jan 21 '13 at 08:12
  • I'm using Eclipse 3.7 with Maven, hence findbugs-maven-plugin:2.5.2 is used. Running it with "mvn site" for the bug reporting. – Eugene Jan 21 '13 at 08:42

2 Answers2

9

I think FindBugs does not undestand that IOUtils.closeQuietly(out) closes out.

Anyway it is enough to close ObjectOutputStream and it will close underlying ByteArrayOutputStream. This is ObjectOutputStream.close implementation

public void close() throws IOException {
    flush();
    clear();
    bout.close();
}

so you can simplify your code

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream s = new ObjectOutputStream(out);
    try {
        s.writeObject(1);
    } finally {
        IOUtils.closeQuietly(s);
    }

or if you are in Java 7

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try (ObjectOutputStream s = new ObjectOutputStream(out)) {
        s.writeObject(1);
    }
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
1

It means that s.close() will try to close underlying stream, but it may fail to do it. So to be sure you should close it on your own also. Try to add out.close() and see if warning disappears.

partlov
  • 13,789
  • 6
  • 63
  • 82
  • Surely FindBugs would then highlight the `out = new ByteArrayOutputStream();` line? – Duncan Jones Jan 21 '13 at 07:54
  • It highlights line `s = new ObjectOutputStream(out);` because inside it is `out.close()`. It is just a warning that it can lead to errors. If that line wouldn't exist he will see no warnings. – partlov Jan 21 '13 at 07:58