StrictMode жалуется на то, что InputStream не закрывается - PullRequest
8 голосов
/ 01 марта 2012

Я получаю следующее нарушение, сообщенное StrictMode в Android.

02-05 04: 07: 41.190: ERROR / StrictMode (15093): ресурс был получен на трассировке прикрепленного стека, но никогда не выпускается. См. Java.io.Закрыть для информация о том, как избежать утечек ресурсов. 02-05 04: 07: 41.190: ОШИБКА / StrictMode (15093): java.lang.Throwable: явное завершение метод 'close' не вызывается

Это болтовня о том, что потоки не закрываются должным образом. Однако не должно ли закрытие in закрывать основные потоки? В чем может быть причина отмеченной ошибки?

    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
        }
    }

Ответы [ 4 ]

10 голосов
/ 25 сентября 2012

Глядя на исходный код, конструкторы для ObjectInputStream и BufferedInputStream могут выдавать исключения, из-за которых объект FileInputStream будет размещен в следующей строке , но переменная in все равно будет нулевой:

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

Поскольку in равно нулю, когда мы добираемся до блока finally, этот открытый объект FileInputStream не будет закрыт вашим методом closeQuietly(), что в конечном итоге приведет к жалобе StrictMode:

Самое простое исправление, которое я бы предложил, - разделить это распределение на 3 переменные и вызвать closeQuietly() для каждой, возможно, что-то вроде этого:

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;
}
0 голосов
/ 27 сентября 2012
in = new ObjectInputStream(new BufferedInputStream(
                         new FileInputStream(mFile), STREAM_BUFFER_SIZE));

В этом примере кода вы закрываете только ObjectInputStream, но не BufferedInputStream или FileInputStream, вам нужно закрыть их все.

0 голосов
/ 24 сентября 2012

Код должен работать, если вы не используете ProGuard, который может немного испортить байт-код.

FileInputStream имеет хуки для CloseGuard, который проверяется в finalize (), если экземпляр был закрыт,Вот почему я думаю, что это должно работать.Вопрос в том, была ли вызвана погода close() или нет?

Я думаю, что FileInputStream был создан (потому что StrictMode выбросил исключение), но затем было окончательно сгенерировано исключение и где-то игнорировано.

    try {
        if (input != null) {
            input.close();
        }
    } catch (Exception ioe) {
        // check exception here
    }
0 голосов
/ 01 марта 2012

Если вы посмотрите на источник ObjectOutpuStream, вы увидите, что его метод close закрывает основной поток. В строгом режиме Android, как и во многих других инструментах анализа кода, есть ложные срабатывания, которые можно игнорировать или переписать, чтобы он не жаловался (встроенный метод closeQuietly).

...