我在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版本:
它是如何做到的?
答案 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的默认缓冲区大小在测试中是有效的。