2013-01-10 61 views
10

我知道這裏有幾個類似的有問題的問題,但其中大多數人已經忘記在其流上放置close()指令。這裏有所不同。資源泄漏:'in'永遠不會關閉,儘管它已關閉

可以說我有以下的小例子:

public void test() throws IOException 
{ 
    InputStream in; 
    if(file.exists()) 
    { 
     in = new FileInputStream(file); 
    } 
    else 
    { 
     in = new URL("some url").openStream(); 
    } 
    in.close(); 
} 

這給我在Eclipse(朱諾SR1)一Resource leak: 'in' is never closed警告。 但是當我移動到in.close()的條件塊,警告消失:

public void test() throws IOException 
{ 
    InputStream in; 
    if(file.exists()) 
    { 
     in = new GZIPInputStream(new FileInputStream(file)); 
     in.close(); 
    } 
    else 
    { 
     in = new URL("some URL").openStream(); 
    } 
} 

這到底是怎麼回事?

+0

警告其中。 IDE? Java編譯?哪個IDE?哪個版本? – Gimby

+0

*「......警告消失:」*。哪些警告? –

+3

你應該有一個try/finally塊。在finally塊中關閉流,以確保在拋出異常時不會錯過。 – duffymo

回答

5

以下是我會寫:

public void test() throws IOException 
{ 
    InputStream in = null; 
    try { 
     if(file.exists()) { 
      in = new FileInputStream(file); 
     } else { 
      in = new URL("some url").openStream(); 
     } 
     // Do something useful with the stream. 
    } finally { 
     close(in); 
    } 
} 

public static void close(InputStream is) { 
    try { 
     if (is != null) { 
      is.close(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+1

謝謝,這真的有用。然而,我仍然不明白它將如何發生'in!= null',並且'FileInputStream'構造函數拋出異常。 讓我們假設,'FileInputStream'構造函數拋出一個異常。這意味着'in'仍然是空的。因此,'is.close()'語句被忽略了嗎? – theV0ID

+1

我更願意接受你的感謝。你的例子很有意思,因爲你只是在調用構造函數。但是,如果您實際使用InputStream,則讀取失敗時可能會引發異常。沒有什麼是「被忽視」的。這不是程序的工作方式。 – duffymo

+0

從Java 7開始,您可以使用資源嘗試。 – dramzy

4

我懷疑警告是不正確的。它可能會檢查您是否在相同範圍內關閉了流。在第二種情況下,您沒有關閉第二個流。

+1

我同意這個答案,我已經提出了毫無意義和無法解釋的downvote。警告顯然是不正確的。第二個例子,其中真的*是*缺少關閉證明了這一點。 – EJP

6

因爲IO異常,則可能會遇到資源泄漏(poentially)

試着做以下幾點:

public void test() throws IOException 
{ 
    InputStream in= null; 
    try { 
     if(file.exists()) 
     { 
      // In this case, if the FileInputStream call does not 
      // throw a FileNotFoundException (descendant of IOException) 
      // it will create the input stream which you are wrapping 
      // in a GZIPInputStream (no IO exception on construction) 
      in = new GZIPInputStream(new FileInputStream(file)); 
     } 
     else 
     { 
      // Here however, if you are able to create the URL 
      // object, "some url" is a valid URL, when you call 
      // openStream() you have the potential of creating 
      // the input stream. new URL(String spec) will throw 
      // a MalformedURLException which is also a descendant of 
      // IOException. 
      in = new URL("some url").openStream(); 
     } 

     // Do work on the 'in' here 
    } finally { 
     if(null != in) { 
      try 
      { 
       in.close(); 
      } catch(IOException ex) { 
       // log or fail if you like 
      } 
     } 
    } 
} 

做上述將確保你已經關閉了流或至少盡最大努力這樣做。

在您的原始代碼中,您聲明瞭InputStream但從未初始化過。首先這是一種糟糕的形式。如上所示,將其初始化爲null。我的感覺是,我目前沒有運行Juno,因爲它看到InputStream'in',可能會讓它穿過所有的障礙和障礙,以達到您要使用它的地步。不幸的是,正如有人指出的,你的代碼對於一個例子來說有點不妥。這樣做,因爲我已經詳細以及@duffymo你會擺脫警告。

+0

謝謝,這個工程。不過,我對這個解決方案有一個理解問題。這與這個答案相同:[鏈接](http://stackoverflow.com/a/14255849/1444073) 你能解釋一下嗎? – theV0ID

0

如果文件不存在並且您嘗試關閉不存在的文件,那麼您的流中可能無法初始化。

你的第二個例子也需要一個關閉語句以避免泄漏。

+0

否。如果'in'不能被初始化,則引發異常並且未達到in.close()。這段代碼不可能「試圖關閉一個不存在的文件」。 – EJP

0

這同一個Eclipse的報告可能發生,當你明確地拋出一個異常,你已經打開了你的資源之後,如:

public void method() throws IOException { 
    BufferedReader br = new BufferedReader(new FileReader("myfile.txt")); 
    while (br.ready()) { 
     String line = br.readLine(): 
     if (line.length() > 255) { 
     throw new IOException("I am some random IOException"); 
     } 
    } 
    br.close(); 
} 

這是一些做作用於演示目的的代碼,所以不要太難。

如果有人註釋掉該行,警告消失。當然,你反而希望確保資源被正確關閉。你可以這樣做:

if (line.length() > 255) { 
    br.close(); 
    throw new IOException("I am some random IOException"); 
} 

雖然在這種情況下不要依賴Eclipse警告。養成使用try/finally方法的習慣,確保資源正確並始終關閉。

0

我有類似:

InputStream content = httpResponse.getEntity()==null?null:httpResponse.getEntity().getContent(); 

,讓同一warrning。但如果我離開它就像這樣:

InputStream content =httpResponse.getEntity().getContent(); 

我沒有收到任何warrnings。不奇怪或者是什麼?

- 我希望我的信息是增加知識的原始問題。謝謝!

+0

,如果我寫在一個正常的IF語句,我再次收到沒有warrnings。嗯... – Edwin

相關問題