8

AndroidのStrictModeによって次の違反が報告されています。

02-05 04:07:41.190: ERROR/StrictMode(15093): 添付のスタック トレースでリソースが取得されましたが、解放されませんでした。リソース リークを回避する方法については、java.io.Closeable を参照してください。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

4 に答える 4

10

ソース コードを見ると、 と の両方のコンストラクターがObjectInputStream例外BufferedInputStreamをスローFileInputStreamし、次の行でオブジェクトが割り当てられる可能性がありますが、in変数は依然として null です。

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

ブロックにin到達したときに null であるため、開いているオブジェクトはメソッドによって閉じられず、最終的に不平を言う原因になります:)finallyFileInputStreamcloseQuietly()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;
}
于 2012-09-24T21:17:54.623 に答える
0
in = new ObjectInputStream(new BufferedInputStream(
                         new FileInputStream(mFile), STREAM_BUFFER_SIZE));

このコードサンプルでは、 ​​またはを閉じるのではObjectInputStreamなく、すべてを閉じる必要があります。BufferedInputStreamFileInputStream

于 2012-09-27T14:06:05.870 に答える
0

バイトコードを少し混乱させる可能性のあるProGuardを使用している場合を除いて、コードは機能するはずです。

FileInputStreamCloseGuardインスタンスが閉じられた場合にfinalize()でチェックされるフックがあります。そういうわけで私はそれがうまくいくはずだと思います。問題は、天気close()が呼び出されたかどうかです。

FileInputStreamこれは(StrictModeが例外をスローしたために)作成されたと思いますが、最終的に例外がスローされ、どこかで無視されました。

    try {
        if (input != null) {
            input.close();
        }
    } catch (Exception ioe) {
        // check exception here
    }
于 2012-09-24T13:08:48.537 に答える
0

ObjectOutpuStream ソースを見ると、その close メソッドが基になるストリームを閉じていることがわかります。他の多くのコード分析ツールと同様に、Android の厳密モードには誤検知がありますが、無視するかコードを書き直して、文句を言わないようにすることができます (インラインの closeQuietly メソッド)。

于 2012-03-01T12:43:32.787 に答える