2012-10-16 72 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也不會刪除該警告。 –