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 编译器问题。以下是代码,我不得不创建一个虚拟的 openFileOutput() 方法,因为它在 java 中不可用:

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 和其他读者清楚,而不是发表评论。

我已经使用当前版本的平台工具链(2012 年 10 月 14 日修订版)在 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不会关闭。将 a 添加finallytry-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 回答