10

同様の資格のある質問がいくつかあることは知っていますが、それらのほとんどはclose()、ストリームにディレクティブを配置することを単に忘れています。これはここでは違います。

次の最小限の例があるとしましょう。

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

これによりResource leak: 'in' is never closed、Eclipse(Juno 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();
    }
}

ここで何が起こっているのですか?

4

6 に答える 6

7

IO例外のため、リソースリークが発生する可能性があります(潜在的に)

次のことを試してください。

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と同様に詳細に説明したようにこれを行うと、警告が表示されなくなります。

于 2013-01-10T10:33:20.307 に答える
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();
    }
}
于 2013-01-10T10:35:00.917 に答える
4

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

于 2013-01-10T10:31:45.290 に答える
0

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

2番目の例でも、リークを回避するためにcloseステートメントが必要になります。

于 2013-01-10T10:33:37.600 に答える
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 / finalアプローチを使用して、リソースが正しく一貫して閉じられていることを確認する習慣を身に付けてください。

于 2014-05-09T14:26:22.683 に答える
0

私は次のようなものを持っています:

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

それは同じ警告を与えます。しかし、私がそれをこのように残すと:

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

警告はありません。変じゃないですか?

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

于 2015-06-23T07:38:36.860 に答える