19

Many I/O resources in Java such as InputStream and OutputStream need to be closed when they are finished with, as discussed here.

How can I search my project for places where such resources are not being closed, e.g. this kind of error:

private void readFile(File file) throws IOException {
    InputStream in = new FileInputStream(file);
    int nextByte = in.read();
    while (nextByte != -1) {
        // Do something with the byte here
        // ...
        // Read the next byte
        nextByte = in.read();
    }
    // Oops! Not closing the InputStream
}

I've tried some static analysis tools such as PMD and FindBugs, but they don't flag the above code as being wrong.

Andrew Swan
  • 13,427
  • 22
  • 69
  • 98
  • 3
    FindBugs seems to be able to detect this, though: http://stackoverflow.com/questions/2570820/findbugs-may-fail-to-close-stream-is-this-valid-in-case-of-inputstream – Thilo Sep 08 '11 at 04:43
  • 1
    Sounds like you need to adjust which rules FindBugs checks – Chip McCormick Sep 08 '11 at 10:07

3 Answers3

7

It's probably matter of setting - I ran FindBugs through my IDE plugin and it reported OS_OPEN_STREAM.

Rostislav Matl
  • 4,294
  • 4
  • 29
  • 53
  • 1
    Can you elaborate what setting need to be done in the FindBugs? IMO, this should have been enabled by default, given the side effects of application crash when it ran out of ulimit. – bram Feb 18 '15 at 01:20
6

If FindBugs with modified rules doesn't work for you, another slower approach is heap analysis. VisualVM allows you to query all objects of a specific type that are open at any given time within a heap dump using OQL. You could then check for streams open to files that shouldn't be accessed at that point in the program.

Running it is as simple as:

%>jvisualvm

Choose the running process. Choose option save heap dump (or something to that effect), open the heap dump and look at class instances for file streams in the browser, or query for them.

Chip McCormick
  • 744
  • 4
  • 17
  • 1
    I think this method does not work if the associated stream only leaves memory allocation on the native memory (vm_allocate) and you want to track down those streams. They already have been garbage collected (so they don't show up on the heap), but they did not clean up the native memory. – Baptiste Pernet Jan 06 '21 at 19:53
  • https://stackoverflow.com/questions/13312229/where-did-jvisualvm-go – pdem Nov 16 '22 at 15:16
0

In Java 7, they added a feature of using closable resources in current scope (so called try-with-resources), such as:

public void someMethod() {
    try(InputStream is = new FileInputStream(file)) {
        //do something here
    } // the stream is closed here
}

In older versions, the common technique is using try-catch-finally chain.

Andrew Swan
  • 13,427
  • 22
  • 69
  • 98
Andrey Atapin
  • 7,745
  • 3
  • 28
  • 34