Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StrictMode complains about InputStream not being closed

I'm getting the following violation reported by StrictMode in Android.

02-05 04:07:41.190: ERROR/StrictMode(15093): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. 02-05 04:07:41.190: ERROR/StrictMode(15093): java.lang.Throwable: Explicit termination method 'close' not called

It is cribbing about not closing streams properly. However, shouldn't closing in close the underlying streams? What could be the reason for the flagged error?

    private ArrayList<Uri> loadPath() {
        ArrayList<Uri> uris = new ArrayList<Uri>();
        if (mFile.exists()) {
            ObjectInputStream in = null;
            try {
                in = new ObjectInputStream(new BufferedInputStream(
                         new FileInputStream(mFile), STREAM_BUFFER_SIZE));
                ArrayList<String> strings = new ArrayList<String>();
                strings.addAll((ArrayList<String>) in.readObject());
                for (String string : strings) {
                    uris.add(Uri.parse(string));
                }
            } catch (Exception e) {
                mFile.delete();
            } finally {
                IOUtils.closeQuietly(in);
            }
        }
        return uris;
     }

    public static void closeQuietly(InputStream input) {
        try {
            if (input != null) {
                input.close();
            }
        } catch (IOException ioe) {
            // ignore
        }
    }
like image 950
Roopesh Kohad Avatar asked Mar 01 '12 11:03

Roopesh Kohad


1 Answers

Looking at the source code, the constructors for both ObjectInputStream and BufferedInputStream can throw exceptions which would cause a FileInputStream object to be allocated on the following line, but the in variable will still be null:

            in = new ObjectInputStream(
                    new BufferedInputStream(
                            new FileInputStream(mFile), 
                    STREAM_BUFFER_SIZE)
            );

Since in is null when we get to the finally block, that open FileInputStream object will not be closed by your closeQuietly() method, causing StrictMode to complain eventually :)

The simplest fix I would suggest is to split that allocation into 3 variables and call closeQuietly() on each, maybe something like this:

private ArrayList<Uri> loadPath() {
    final ArrayList<Uri> uris = new ArrayList<Uri>();
    if (mFile.exists()) {
        ObjectInputStream ois = null;
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream(mFile);
            bis = new BufferedInputStream(fis, STREAM_BUFFER_SIZE);
            ois = new ObjectInputStream(bis);
            final ArrayList<String> strings = new ArrayList<String>();
            strings.addAll((ArrayList<String>) ois.readObject());
            for (final String string : strings) {
                uris.add(Uri.parse(string));
            }
        } catch (final Exception e) {
            mFile.delete();
        } finally {
            closeQuietly(fis);
            closeQuietly(bis);
            closeQuietly(ois);
        }
    }
    return uris;
}
like image 186
Joe Avatar answered Sep 30 '22 17:09

Joe