2013-01-10 15 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でResource leak: 'in' is never closed警告(ジュノSR1)を得た:

は、私は、次の最小限の例を考えてみましょう。 しかし、私は、条件付きブロックに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

は、私はそれを書くだろう方法ですデモンストレーションの目的のためにコード化してください。

行をコメントアウトすると、警告が消えます。もちろん、そのリソースが適切に閉じられていることを確認する必要があります。あなたはそうすることができます:

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

この場合、Eclipseの警告に頼らないでください。 try/finallyアプローチを使用して、リソースが正しく、一貫して閉じられていることを確認する習慣を身につけてください。同じwarrningを与える

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

+1

ありがとう、これは実際に動作します。しかし、私はまだ 'in!= null'がどのように起こり、' FileInputStream'コンストラクタによって例外がスローされるのかまだ分かりません。 'FileInputStream'コンストラクタは例外をスローします。これは 'in'がまだnullであることを意味します。したがって、 'is.close()'文は無視されますか? – theV0ID

+1

私はあなたのおかげでupvoteと受け入れを好むだろう。あなたの例は、何もしていないのにコンストラクタを呼び出すので、工夫されています。しかし、実際にInputStreamを使用していた場合、読み込みが失敗した場合、例外がスローされる可能性があります。そして、何も "無視されます"。それはプログラムの仕組みではありません。 – duffymo

+0

Java 7からは、リソースを使って試してみることができます。 – dramzy

4

警告が間違っていると思われます。同じ範囲でストリームを閉じることを確認している可能性があります。 2番目のケースでは、2番目のストリームを終了していません。

+1

私はこの答えに同意し、私は無意識で説明できないdownvoteをupvotedしました。警告ははっきりと間違っています。本当に*が*欠落している2番目の例は、その点を証明しています。 – 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が潜在的にすべてのフープとハードルを通って、あなたが使用しようとしているポイントに到達する可能性があることがわかります。残念なことに、誰かが指摘しているように、あなたのコードは例のために少しばかげています。私が詳細に書いたようにこれを行うと、あなたは警告を取り除くでしょう。

+0

ありがとう、これは動作します。しかし、私はこの解決策には理解している問題があります。この回答の場合と同じです:[リンク](http://stackoverflow.com/a/14255849/1444073) これを説明できますか? – theV0ID

0

ファイルが存在せず、存在しないファイルを閉じようとすると、ストリームが初期化されないことがあります。

2番目の例では、リークを防ぐためにclose文も必要です。あなたが明示的に例外をスローするとき

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(); 
    } 
} 
+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(); 
} 

ここ

0

は、私のようなものを持っています。しかし、私がこのままにした場合:

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

私は何の保証も受けていません。奇妙なことではないですか?

- 私の情報が元の質問に知識を追加してくれることを願っています。ありがとう!

+0

通常のIFステートメントで書いても、もう一度私は何の懸念も受けません。うーん... – Edwin

関連する問題