Background

There is a nice function I use on IOUtils called "closeQuietly" , which closes the stream no matter what is in there.

for example:

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

Somehow, it also hides the warning on Eclipse when I call it in the finally block , of "Resource leak: 'input' is not closed at this location" .

This means that in the above code, there is no such warning.

The problem

I don't understand how it hides the warning on the "outside world" of itself.

What I've tried

I've tried to check it out by copying the code of this library (example here), but the warning appears when I use it on the new class. It doesn't make sense...

here's a sample code i've created to show that the warning will occur on your own classes:

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) {
        }
    }
}

usage:

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

Here's what I see, including the Eclipse version I have being installed:

enter image description here

The question

How does it do it?

有帮助吗?

解决方案

So why does it work for IOUtils? The eclipse team did something very plain - they hardcoded the methods! In previous versions of eclipse the warning was also there however starting from version 4.3 M4 it was gone since they fixed it:

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)

For details see here - especially at the comments at the end...

UPDATE: So what does it mean for you? You have to use one of the obove methods or live with the warning. The check is basically not sophisticated and doesn't check the next level.

Update II: They basically hardcoded the file names. Maybe it is easer to understand with source code. Imagine this is the eclipse code checking for the warning:

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

=> The result is, that you don't have a chance to remove the warning other to directly use close() (not in a sub method!) or to use one of the three methods listed above.

Update III: Have a look at the following class TypeConstants.java. Do you see the hardwired names in there? If you want to make it work with your code you need to add your class and method name there and then recompile eclipse. Then look at the class MessageSend.java starting from line 90.

其他提示

I am unable to reproduce this problem on my Eclipse installation, so cannot test my explanation. However, This is what we find in 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

Resource wrappers and resource-free closeables

The JDK defines a few classes which implement Closeable but do not directly represent a resource at the level of the operating system.

java.io.StringReader is an example of a closeable that doesn't require calling close() because no operating system resources are held that would require clean-up. The analysis uses an explicit white list to detect classes from java.io that fall in this category. No resource leak warnings are issued regarding these classes.

Instances of classes like java.io.BufferedInputStream are wrappers around another resource (where wrappers can be applied at multiple levels). Also these objects do not directly represent an operating system resource. If the wrapped resource is closed, the wrapper doesn't need closing. Conversely, if a wrapper is closed this will include closing of the wrapped resource. The analysis has a second white list for detecting wrapper resources, and will recognize whether the underlying actual resource will be closed directly or indirectly via the wrapper. Either one suffices to silence warnings regarding resource leaks. The white list contains classes from java.io, java.util.zip, java.security, java.beans and java.sound.sampled.

Hint: It is generally preferable/safest to close the outermost wrapper, not a wrapped resource.

According to the IOUtils documentation, All the methods in this class that read a stream are buffered internally. This means that there is no cause to use a BufferedInputStream or BufferedReader. The default buffer size of 4K has been shown to be efficient in tests.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top