116

Why does Eclipse give me the warming "Resource leak: 'in' is never closed" in the following code?

public void readShapeData() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
Patrick Brinich-Langlois
  • 1,381
  • 1
  • 15
  • 29
user1686995
  • 1,261
  • 2
  • 9
  • 3
  • 12
    **To future readers:** many answers state that you must close the scanner, in order to close the underlying resource. While this is true in general, *standard in* is an exception. Closing it will prevent you from reading it again, which is typically undesired. As a rule of thumb: don't close what you didn't open. – MC Emperor Aug 22 '21 at 23:39

15 Answers15

99

Because you don't close your Scanner

in.close();
nogard
  • 9,432
  • 6
  • 33
  • 53
  • 58
    This will close the `Scanner` and silence the warning, but it will also close `System.in` which is typically not desirable. – Stuart Cook Dec 19 '12 at 05:55
  • 1
    @StuartCook +1. Something to keep an eye on. – informatik01 Mar 15 '13 at 22:29
  • 10
    Why do we need to close Scanner ? What is meant by "resource leak" ? – Erran Morad May 04 '14 at 22:17
  • 2
    @nogard: this your answer is really helpful.. but when i use in.close();.. again it shows in cannot be resolved.. i have a code without exception handling.. thanks – pcs Jun 09 '15 at 08:45
  • 11
    @StuartCook, you forgot to mention **why** closing `System.in` is typically not desirable. It's because you won't be able to read from it again. I. e. you will get `java.util.NoSuchElementException: No line found` if you try to call `(new Scanner(System.in)).nextLine()` for example. – Petr Bodnár Nov 16 '19 at 12:23
  • All in all, the general recommendation for `System.in` should be NOT to close the wrapping `Scanner` and to add `@SuppressWarnings("resource")` to the enclosing method if you need to make your compiler / Eclipse happy. Or did I overlook something? – Petr Bodnár Nov 16 '19 at 12:28
  • I found this topic very informational helpful keep it up! – It's Joker Apr 02 '22 at 06:16
71

As others have said, you need to call 'close' on IO classes. I'll add that this is an excellent spot to use the try - finally block with no catch, like this:

public void readShapeData() throws IOException {
    Scanner in = new Scanner(System.in);
    try {
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
    } finally {
        in.close();
    }
}

This ensures that your Scanner is always closed, guaranteeing proper resource cleanup.

Equivalently, in Java 7 or greater, you can use the "try-with-resources" syntax:

try (Scanner in = new Scanner(System.in)) {
    ... 
}
Eric Lindauer
  • 1,813
  • 13
  • 19
14

You need call in.close(), in a finally block to ensure it occurs.

From the Eclipse documentation, here is why it flags this particular problem (emphasis mine):

Classes implementing the interface java.io.Closeable (since JDK 1.5) and java.lang.AutoCloseable (since JDK 1.7) are considered to represent external resources, which should be closed using method close(), when they are no longer needed.

The Eclipse Java compiler is able to analyze whether code using such types adheres to this policy.

...

The compiler will flag [violations] with "Resource leak: 'stream' is never closed".

Full explanation here.

Will
  • 6,601
  • 3
  • 31
  • 42
7

It is telling you that you need to close the Scanner you instantiated on System.in with Scanner.close(). Normally every reader should be closed.

Note that if you close System.in, you won't be able to read from it again. You may also take a look at the Console class.

public void readShapeData() {
    Console console = System.console();
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
    ...
}
Alex
  • 25,147
  • 6
  • 59
  • 55
  • 4
    Note that `System.console()` is not available when running an application via Eclipse, which can be a hassle during development. – Stuart Cook Dec 19 '12 at 05:59
7
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

above line will invoke Constructor of Scanner class with argument System.in, and will return a reference to newly constructed object.

It is connected to a Input Stream that is connected to Keyboard, so now at run-time you can take user input to do required operation.

//Write piece of code 

To remove the memory leak -

in.close();//write at end of code.
Sampada
  • 2,931
  • 7
  • 27
  • 39
Aashi
  • 489
  • 1
  • 5
  • 12
6

If you are using JDK7 or 8, you can use try-catch with resources.This will automatically close the scanner.

try ( Scanner scanner = new Scanner(System.in); )
  {
    System.out.println("Enter the width of the Rectangle: ");
    width = scanner.nextDouble();
    System.out.println("Enter the height of the Rectangle: ");
    height = scanner.nextDouble();
  }
catch(Exception ex)
{
    //exception handling...do something (e.g., print the error message)
    ex.printStackTrace();
}
JakeD
  • 2,788
  • 2
  • 20
  • 29
uzumas
  • 632
  • 1
  • 8
  • 23
  • 1
    Note that the catch clause is not mandatory. If you just want to ensure the resource is closed even in the event of an exception, but leave the treatment of exceptions as in the OP's original code (namely, not caught at all) you can just use `try` as shown and not use a `catch` clause. – user118967 Jun 27 '20 at 05:14
5

adding private static Scanner in; does not really fix the problem, it only clears out the warning. Making the scanner static means it remains open forever (or until the class get's unloaded, which nearly is "forever"). The compiler gives you no warning any more, since you told him "keep it open forever". But that is not what you really wanted to, since you should close resources as soon as you don't need them any more.

HTH, Manfred.

user2393042
  • 71
  • 1
  • 3
5

Okay, seriously, in many cases at least, this is actually a bug. It shows up in VS Code as well, and it's the linter noticing that you've reached the end of the enclosing scope without closing the scanner object, but not recognizing that closing all open file descriptors is part of process termination. There's no resource leak because the resources are all cleaned up at termination, and the process goes away, leaving nowhere for the resource to be held.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
3

You should close your Scanner when you're done with it:

in.close();
Dan W
  • 5,718
  • 4
  • 33
  • 44
2

Generally, instances of classes that deal with I/O should be closed after you're finished with them. So at the end of your code you could add in.close().

arshajii
  • 127,459
  • 24
  • 238
  • 287
1

The Scanner should be closed. It is a good practice to close Readers, Streams...and this kind of objects to free up resources and aovid memory leaks; and doing so in a finally block to make sure that they are closed up even if an exception occurs while handling those objects.

  • This answer actually helps OP know why he should close the thing. Sure, he can read the doc and see "`scanner.close()`", but this answer really helps him/her understand what's going on. + 1 – hyper-neutrino Nov 11 '15 at 03:03
0
private static Scanner in;

I fixed it by declaring in as a private static Scanner class variable. Not sure why that fixed it but that is what eclipse recommended I do.

zachdyer
  • 611
  • 1
  • 9
  • 17
0
Scanner sc = new Scanner(System.in);

//do stuff with sc

sc.close();//write at end of code.
Community
  • 1
  • 1
tejas
  • 9
  • 1
0

Solution:

    your_object_name.close();

Explanation:

  • Close the scanner of the relevant object (after it has been used) to prevent the resource leak.

What is a resource leak?

  • They are bugs that arise when a program doesn't release the resources it has acquired. Furthermore, it can lead to resource exhaustion. (Ref: AWS official site)
KuAKu KRK
  • 11
  • 1
-1
in.close();
scannerObject.close(); 

It will close Scanner and shut the warning.

Pritam Banerjee
  • 17,953
  • 10
  • 93
  • 108
HRUTU.Z
  • 1
  • 2