2012-10-16 65 views
0

在我的真实项目中重现问题的简短方法。环境:Android SDK 1.16,Eclipse 4.2.0,Windows。在Save1功能fos = new FileOutputStream(file)资源泄漏:流从未关闭

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

线,警告:创建默认的Android应用程序,将下面的代码添加到MainActivity.java Resource leak: 'fos' is never closed

的同一线上Save2功能:无需警告。

请不要发送未经测试的答案,问题并不像看起来那么简单。将fos.close()添加到该函数的不同部分并没有帮助。

+0

哇。编译器错误?当fos未关闭时,我看不到任何可能的路径。有兴趣地观看.... – Simon

+0

@Simon:如果这是编译器错误,我不在乎 - 我可以编写两个不同的函数。我只是想知道这是否是我的错误。 –

+0

其实,更像是一个Lint bug,但我正在检查它。 – Simon

回答

2

它也走,如果我添加一个finally块的try中,如果块这样的:

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块关闭这个流。

类似的东西..

一个尝试同样的代码在Eclipse中一个简单的Java项目,并仍然得到了警告。所以它看起来是不相关的棉绒或Android。它看起来像eclipse编译器问题。以下是代码,我必须创建一个虚拟openFileOutput()方法,因为它不可用。n 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; 
} 
+0

是的,这消除了警告。我仍然认为这是Lint bug,而不是我的错,因为第二个函数编译没有警告。谢谢。 –

+0

add'if(fos!= null){fos.close(); }'避免'NullPointerException' –

+0

只需检查一个简单的java项目,仍然有相同的警告。所以它看起来像不是棉绒或Android编译器问题.... 我在答案中添加了Java代码... –

0

如果是Exceptionfos将不会被关闭。将finally添加到try-catch将解决此问题。

try 
    { 
     fos = openFileOutput("log", Context.MODE_PRIVATE); 
    } 
    catch(FileNotFoundException e) 
    { 
     return; 
    } 
    //add this: 
    finally { 
     if (fos != null) { 
      fos.close(); 
     } 
    } 
+0

1.您的答案未编译。 2.你正试图改变没有任何警告的地方。 –

+0

如果你尝试打开某些东西,最后关闭它 - 简单的规则。那只是一个“地方”的例子。你应该在每一次尝试中都做到这一点...不必编译知道这一点 - 再次看到接受的答案 –

+0

- 这不应该是现成的解决方案。这提示了你的错误在哪里:确保在每种可能性中资源都将被关闭(如果不为空)。看着你的问题,你不这样做。做到这一点的一种方法是最后使用。 btw既不lint也不编译器会抱怨,如果你遵循这个建议(测试)。并没有这不是一个编译器错误... –

1

这不是一个答案,但是为了清晰起见OP和其他读者而不是评论添加到这里。

我已经在IDEA 11.2 API 15中使用当前版本的平台工具链(Rev 14 Oct 2012)对此进行了测试,并且没有lint警告,编译错误或运行时错误。我强制该方法通过创建异常并将useExternalStorage设置为true和false来遍历每条路径。

我的猜测是这是你的工具链或可能的Eclipse中的一个lint /编译错误(虽然不太可能,Eclipse自己做这样的检查?)。

[编辑]

只是一个想法,(我会测试,但我忘了如何使用Eclipse),但的FileInputStream(文件)可能会引发这将被抛出来的地方在你的调用堆栈一个SecurityException 。如果你抓住它会发生什么?

[编辑]

这是最接近警告我得到的,而不是在所有有关。我相信,这个警告并不在你身上。

Screen shot for IDEA 11.2, API 15, SDK tools rev 14

+0

它看起来最终这将是答案。 –

+0

看我的编辑。可能值得一试。 – Simon

+0

即使用Exception替换FileNotFoundException也不会删除该警告。 –