IOUtils.close如何隐藏“资源泄漏”警告?

时间:2014-01-16 12:18:49

标签: java eclipse stream compiler-warnings resource-leak

背景

我在IOUtils上使用了一个名为“closeQuietly”的函数,它关闭了流,无论它在哪里。

例如:

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

不知何故,当我在finally块中调用它时,它也隐藏了Eclipse上的警告,“资源泄漏:'输入'在此位置没有关闭”。

这意味着在上面的代码中,没有这样的警告。

问题

我不明白它是如何隐藏自身“外部世界”的警告。

我尝试了什么

我试图通过复制此库的代码(例如here)来检查它,但是当我在新类上使用它时会出现警告。这没有意义......

这是我创建的示例代码,用于显示警告将在您自己的类上发生:

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版本:

enter image description here

问题

它是如何做到的?

2 个答案:

答案 0 :(得分:3)

那为什么它适用于IOUtils?日食团队做了一件非常简单的事情 - 他们硬编码方法!在以前的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)

有关详细信息,请参阅here - 尤其是最后的评论......

更新:那么这对您意味着什么?您必须使用其中一个obove方法或使用警告。检查基本上不复杂,不检查下一级别。

更新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;
}

=&GT;结果是,您没有机会删除警告,而不是直接使用close()(不是在子方法中!)或使用上面列出的三种方法之一。

更新III:查看以下课程TypeConstants.java。你看到那里的硬连线名字吗?如果你想让它与你的代码一起工作,你需要在那里添加你的类和方法名,然后重新编译eclipse。然后从第90行开始查看课程MessageSend.java

答案 1 :(得分: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_w6OHY3KOw&bvm=bv.59568121,d.cGU

中找到的内容

资源包装器和无资源可关闭

JDK定义了一些实现Closeable的类,但不直接表示操作系统级别的资源。

java.io.StringReader是一个closeable的示例,它不需要调用close()因为没有操作系统资源被保留需要清理。该分析使用显式白名单来检测属于此类别的java.io中的类。没有针对这些类发布资源泄漏警告。

像java.io.BufferedInputStream这样的类的实例是围绕另一个资源的包装器(其中包装器可以在多个级别应用)。这些对象也不直接表示操作系统资源。如果包装的资源已关闭,则包装器不需要关闭。相反,如果封装器关闭,这将包括关闭包装的资源。该分析具有用于检测包装器资源的第二个白名单,并将识别是否将通过包装器直接或间接关闭基础实际资源。任何一个都足以沉默关于资源泄漏的警告。白名单包含来自java.io,java.util.zip,java.security,java.beans和java.sound.sampled的类。

提示:关闭最外面的包装器而不是包装的资源通常是最好/最安全的。

根据IOUtils文档,此类中读取流的所有方法都在内部进行缓冲。这意味着没有理由使用BufferedInputStream或BufferedReader。已经证明4K的默认缓冲区大小在测试中是有效的。