0

私の実際のプロジェクトで問題を再現する簡単な方法。環境: Android SDK 1.16、Eclipse 4.2.0、Windows。デフォルトの Android アプリケーションを作成し、次のコードを MainActivity.java に追加します。

private void Save1(boolean externalStorage)
{
    String s = "12345";
    File file;
    FileOutputStream fos = null;

    if ( externalStorage )
    {
        try
        {
            file = new File(getExternalFilesDir(null), "log");
            fos = new FileOutputStream(file);                  // Resource leak: 'fos' is never closed
        }
        catch(FileNotFoundException e)
        {
            return;
        }
    }
    else
    {
        try
        {
            fos = openFileOutput("log", Context.MODE_PRIVATE);
        }
        catch(FileNotFoundException e)
        {
            return;
        }
    }

    try
    {
        fos.write(s.getBytes());
        fos.close();
    }
    catch(IOException e)
    {
        return;
    }
}

private void Save2(boolean externalStorage)
{
    String s = "12345";
    File file;
    FileOutputStream fos = null;

    try
    {
        file = new File(getExternalFilesDir(null), "log");
        fos = new FileOutputStream(file);                  // OK
    }
    catch(FileNotFoundException e)
    {
        return;
    }

    try
    {
        fos.write(s.getBytes());
        fos.close();
    }
    catch(IOException e)
    {
        return;
    }
}

fos = new FileOutputStream(file)関数内の行Save1、警告:Resource leak: 'fos' is never closed

関数の同じ行Save2: 警告なし。

テストされていない回答を送信しないでください。問題は見た目ほど単純ではありません。関数のさまざまな部分に追加fos.close()しても役に立ちません。

4

3 に答える 3

2

次のようにifブロックのtryにfinallyブロックを追加すると、それも消えます。

if (externalStorage) {
            try {
                fos = new FileOutputStream(new File(getExternalFilesDir(null),
                        "log"));
            } catch (FileNotFoundException e) {
                return;
            } finally {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            try {
                fos = openFileOutput("log", Context.MODE_PRIVATE);
            } catch (FileNotFoundException e) {
                return;
            }
        }

面白くなってきた…

したがって、try ブロックで Stream を開き、catch ブロックに return ステートメントがある場合は、ストリームを閉じる finally ブロックが必要です。

そんな感じ..

A は、Eclipse の単純な Java プロジェクトで同じコードを試しましたが、それでも警告が表示されました。したがって、lint や android とは関係がないようです。Eclipseコンパイラの問題のようです。以下はコードです。Java では利用できないため、ダミーの openFileOutput() メソッドを作成する必要がありました。

private void Save1(boolean externalStorage) {
    String s = "12345";
    FileOutputStream fos = null;

    if (externalStorage) {
        try {
            fos = new FileOutputStream(new File("c://", "log"));
        } catch (FileNotFoundException e) {
            return;
        }
    } else {
        try {
            fos = openFileOutput("log", -1);
        } catch (FileNotFoundException e) {
            return;
        }
    }

    try {
        fos.write(s.getBytes());
        fos.close();
    } catch (IOException e) {
        return;
    }
}

/**
 * @param string
 * @param i
 * @return
 */
private FileOutputStream openFileOutput(String string, int i)
        throws FileNotFoundException {
        return null;
}
于 2012-10-16T11:27:10.343 に答える
1

これは答えではありませんが、コメントではなく、OP や他の読者にわかりやすくするためにここに追加されています。

プラットフォーム ツール チェーンの現在のバージョン (Rev 14 Oct 2012) を使用して IDEA 11.2 API 15 でこれをテストしましたが、lint 警告、コンパイル エラー、ランタイム エラーはありません。例外を作成し、useExternalStorage を true と false の両方に設定することで、メソッドが各パスを通過するようにしました。

私の推測では、これはツール チェーンまたは Eclipse の lint/compile エラーである可能性があります (可能性は低いですが、Eclipse 自体がこのようなチェックを行っているのでしょうか?)。

[編集]

考えただけですが (テストはしますが、Eclipse の使用方法を忘れてしまいました)、 FileInputStream(file) が SecurityException をスローする可能性があり、これがコール スタックのどこかにスローされる可能性があります。捕まえたらどうなる?

[編集]

これは私が受け取る最も近い警告であり、まったく関係ありません。警告はあなたのせいではないと確信しています。

IDEA 11.2、API 15、SDK ツール rev 14 のスクリーン ショット

于 2012-10-16T11:19:37.217 に答える
0

の場合はException閉まりfosません。finallyに aを追加すると、try-catchこの問題が解決します。

    try
    {
        fos = openFileOutput("log", Context.MODE_PRIVATE);
    }
    catch(FileNotFoundException e)
    {
        return;
    }
    //add this:
    finally {
        if (fos != null) {
            fos.close();
        }
    }
于 2012-10-16T11:14:09.673 に答える