5

バックグラウンド

「closeQuietly」と呼ばれるIOUtilsで使用する素晴らしい関数があり、そこに何が入っていてもストリームを閉じます。

例えば:

InputStream input = null;
try
  {
  ...
  input = connection.getInputStream();
  ...
  } 
catch(Exception e)
  {
  }
finally
  {
  IOUtils.closeQuietly(input);
  }

どういうわけか、「リソースリーク:「入力」はこの場所で閉じられていません」という最終ブロックで呼び出すと、Eclipseの警告も非表示になります。

これは、上記のコードでは、そのような警告がないことを意味します。

問題

それ自体の「外の世界」に関する警告をどのように隠しているのかわかりません。

私が試したこと

このライブラリのコードをコピーして確認しようとしましたが (例はこちら)、新しいクラスで使用すると警告が表示されます。意味がありません...

独自のクラスで警告が発生することを示すために作成したサンプル コードを次に示します。

public class MyIOUtils {
    public static void closeQuietly(final InputStream input) {
        if (input == null)
            return;
        try {
            input.close();
        } catch (final IOException ioe) {
        }
    }

    public static void closeQuietly(final OutputStream output) {
        if (output == null)
            return;
        try {
            output.close();
        } catch (final IOException ioe) {
        }
    }
}

利用方法:

public class Test {
    public void test() {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("dummyFile.txt");
            int t = 0;
            --t;
            if (t < 0)
                return; // here you will get a warning
        } catch (final FileNotFoundException e) {
        } finally {
            MyIOUtils.closeQuietly(inputStream);
        }
    }
}

インストールされているEclipseのバージョンを含めて、私が見ているものは次のとおりです。

ここに画像の説明を入力

質問

それはどのように行うのですか?

4

2 に答える 2

3

では、なぜ IOUtils で機能するのでしょうか。Eclipse チームは非常に単純なことを行いました - 彼らはメソッドをハードコーディングしました! 以前のバージョンの eclipse では警告も表示されていましたが、バージョン 4.3 M4 からは修正されたため、表示されなくなりました。

Released for 4.3 M4 via commit 277792ba446c3713bcfdc898c37875d45fc06c18.

The fix covers the following well-known methods:
- com.google.common.io.Closeables.closeQuietly(Closeable)
- com.google.common.io.Closeables.close(Closeable,boolean)
- org.apache.commons.io.IOUtils.closeQuietly(Closeable)

詳細については、ここを参照してください-特に最後のコメントで...

更新:では、それはあなたにとって何を意味しますか? 上記の方法のいずれかを使用するか、警告を受け入れる必要があります。チェックは基本的に高度ではなく、次のレベルをチェックしません。

Update II: 彼らは基本的にファイル名をハードコーディングしました。ソースコードで理解しやすいかもしれません。これが警告をチェックするEclipseコードであると想像してください:

public boolean showResourceWarning(){

//do somestuff to detect whether a potential ressource warning is shown
...
    if(resourceLeakWarning){
      if(this.checkForExceptions()){
       return false;
      }
    }
 return resourceLeakWarning;
}

private boolean checkForExceptions(){
    if(name.equals("org.apache.commons.io.IOUtils.closeQuietly(Closeable)"){
     return true;
    }
    if(name.equals("com.google.common.io.Closeables.close(Closeable,boolean)")){
     return true;
    }
    if(name.equals("org.apache.commons.io.IOUtils.closeQuietly(Closeable)")){
     return true;
    }
    // code executed for your method:
    return false;
}

=> 結果として、(サブメソッドではなく) close() を直接使用するか、上記の 3 つのメソッドのいずれかを使用する以外に、警告を削除する機会がありません。

更新 III:次のクラスTypeConstants.javaを見てください。そこに固定された名前が表示されますか?コードで動作させたい場合は、そこにクラスとメソッド名を追加してから、Eclipse を再コンパイルする必要があります。次に、 90 行目から始まるクラスMessageSend.javaを見てください。

于 2014-10-24T13:09:28.143 に答える
0

Eclipse インストールでこの問題を再現できないため、説明をテストできません。ただし、これはhttp://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CC0QFjAA&url=http%3A%2F%2Fhelp.eclipse.org%で見つけたものです2Fjuno%2Ftopic%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-avoiding_resource_leaks.htm&ei=r-TeUvumDsXxoASN8IG4CA&usg=AFQjCNHeI8Ojm5VDlFo_9s-V3IvR7qYokw&sig2=jp9_tF3VbR0u_w6OHY3VM.8vc15&v.8b15KOw.

リソースラッパーとリソースフリーのクローザブル

JDK は、Closeable を実装するが、オペレーティング システムのレベルでリソースを直接表さないいくつかのクラスを定義します。

java.io.StringReader は、クリーンアップが必要なオペレーティング システム リソースが保持されていないため、close() の呼び出しを必要としない closeable の例です。この分析では、明示的なホワイト リストを使用して、このカテゴリに分類される java.io からのクラスを検出します。これらのクラスに関して、リソース リークの警告は発行されません。

java.io.BufferedInputStream などのクラスのインスタンスは、別のリソースのラッパーです (ラッパーは複数のレベルで適用できます)。また、これらのオブジェクトは、オペレーティング システムのリソースを直接表すものではありません。ラップされたリソースが閉じている場合、ラッパーを閉じる必要はありません。逆に、ラッパーが閉じられている場合、これにはラップされたリソースのクローズが含まれます。分析には、ラッパー リソースを検出するための 2 つ目のホワイト リストがあり、基になる実際のリソースが直接またはラッパーを介して間接的に閉じられるかどうかを認識します。リソースリークに関する警告を黙らせるには、どちらでも十分です。ホワイト リストには、java.io、java.util.zip、java.security、java.beans、および java.sound.sampled のクラスが含まれています。

ヒント: 一般に、ラップされたリソースではなく、最も外側のラッパーを閉じることが望ましい/最も安全です。

IOUtils のドキュメントによると、ストリームを読み取るこのクラスのすべてのメソッドは内部的にバッファリングされます。これは、BufferedInputStream または BufferedReader を使用する理由がないことを意味します。デフォルトのバッファ サイズである 4K は、テストで効率的であることが示されています。

于 2014-01-21T21:38:33.463 に答える