Java -- Closing Scanner and Resource Leak

SuperCow picture SuperCow · May 13, 2014 · Viewed 32.1k times · Source

I'm learning Java and working on some projects for fun. One issue that I have run in to is that when I use a Scanner object Eclipse warns me that:

Resource Leak: 'scan' is never closed.

So, I added a scan.close(); at the end of my code and that takes care of the warning.

The problem comes in because I have other classes in the same package that also use scanner objects and and Eclipse tells me to close scanner in those classes respectively. However, when I do that it seems like it closes ALL of the scanner objects and I get errors during run time.

Here is an example of what causes the error:

import java.util.Scanner;
public class test2 {
    public static void main(String [] args) {
        Scanner scan = new Scanner(System.in);
        int test = 0;
        do {    
            //Do stuff
            test = scan.nextInt();
            System.out.println(test);

            scanTest scanTest = new scanTest();
            scanTest.test();
        } while (test != 0);

        scan.close();       
    }
}

import java.util.Scanner;
public class scanTest { 
    public void test() {
        Scanner scanner = new Scanner(System.in);
        int blah = scanner.nextInt();
        System.out.println(blah);
        scanner.close();
    }
}

After scanner is closed in the scanTest class and the do loop in test2 is entered again an error occurs at the line test = scan.nextInt();

I tried moving the creation of the scanner object into the do loop just to make a new object every time as well but the error still occurs.

Not sure why this is happening or how I can make sure all my I/O objects are closed out without running into problems.

One post I came across mentioned that when System.in is closed I cannot be re-opened. If this is the case would I just need to make sure a scanner object with System.in is closed at the very end of the program and @suppress all of the other scanner warnings in other classes? Or would that still leave all those scanner objects open (bad)?

Answer

Edwin Buck picture Edwin Buck · May 13, 2014

First, this is no memory leak.

Second, when you close a stream wrapper, the default implementation is for it to close the stream that it wraps. This means that the first time you close your Scanner (as it is written), yes, you close System.in.

In general, one would like to avoid closing System.in if they were meaning to read from System.in again. The best way to go about this depends on your program.

One might copy the information from System.in into a buffer of some sort and then scan the buffer. One might not close the Scanner, reusing it in other locations. One might even de-reference the Scanner for garbage collection and create multiple new Scanners on System.in.

These solutions are not all equivalent, some are considered much better than others; but, it all depends on the calling program. Experiment with a few, and if you run into a problem, open a new StackOverflow question where you show the relevant portions of your code, a description of the problem, the example input, and the wrong output (along with the desired output).

Good luck.