2

In the line i marked with //D, there is a one-time use with the object instance Scanner. but its memory witll stay in the heap as long as the program plays(which is forever). why the garbage collector wont delete this instance object? how can i change the code so the garbage collector will delete this instance due the program? thanks

package Try;

import java.util.Random;
import java.util.Scanner;

public class Foo1 extends Thread {

    private int min_, max_;
    Foo1(int max, Integer min) {

    max_ = max;
    min_ = min.intValue();
    }

    public void run() {

        Random rand_gen = new Random();
        while(true) {
            try {
                Thread.sleep(rand_gen.nextInt(max_-min_) + min_);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("you got new message");
        }
    }

    public static void main(String[] args){

        System.out.println("Insert 1 to start"); 

        Scanner sc = new Scanner(System.in); // D

        int i = sc.nextInt();

        if (i == 1) {
            Foo1 f1;
            int max = 1000;
            Integer min = new Integer(1000);
            Foo1 f2 = new Foo1(max, min);
            f1 = f2; // A
            f1.start();
        }
    }
}
  • 1
    How are you determining that the `Scanner` stays in memory? Are you sure the garbage collector has run? – Slaw Feb 09 '20 at 20:56
  • 4
    You've got two answer answering your question, but what you need to know: There's hardly ever a point in doing what you asked for. Sometimes, you need to ensure that something get collected ASAP, but this happens maybe once a year... – maaartinus Feb 10 '20 at 01:26

2 Answers2

0

how can i change the code so the garbage collector will delete this instance due the program?

You should set the value of the object to null. The garbage collector will then free the heap memory used by this object.

public static void main(String[] args){

    System.out.println("Insert 1 to start"); 

    Scanner sc = new Scanner(System.in); // D

    int i = sc.nextInt();
    sc = null;

    if (i == 1) {
        Foo1 f1;
        int max = 1000;
        Integer min = new Integer(1000);
        Foo1 f2 = new Foo1(max, min);
        f1 = f2; // A
        f1.start();
    }
}

The reason why it is not removed automatically at the end of the method is because you initialize it in the main-method. In other words: the main method stops when the application stops.

apt-get_install_skill
  • 2,818
  • 10
  • 27
0

You can delete the reference to the scanner by setting it to null i.e. sc = null.

-OR-

If you do not need Scanner anymore, you can close it after using it:

int i = sc.nextInt();
sc.close();

Even better is to use try-with-resources as follows:

int i;
try (Scanner sc = new Scanner(System.in)) {
    i = sc.nextInt();
}

Note that sc.close() closes the scanner and releases the resource while sc = null deletes the reference to the scanner but the resource may still remain open.

Warning: Never close the Scanner for System.in if you still need it for more inputs from System.in as closing the Scanner will also close System.in. Consider the following code:

String s;
System.out.print("Enter a text: ");
try (Scanner sc = new Scanner(System.in)) {
    s = sc.nextLine();
}

try (Scanner in = new Scanner(System.in)) {
    System.out.print("Enter another text: ");
    s = in.nextLine();
}

Trying to execute the code given above will result in:

Enter a text: hello
Enter another text: Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
    at Main.main(Main.java:14)
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • thanks! now the question is whats better? to sc = null; or to sc.close(); ? – Lorin Sherry Feb 09 '20 at 20:50
  • 1
    You almost never want to close a `Scanner` that uses `System.in` as its source of data, as that will close `System.in` as well. – Slaw Feb 09 '20 at 20:54
  • @Slaw i am confused :\ – Lorin Sherry Feb 09 '20 at 21:21
  • 2
    @LorinSherry you should do neither, as that single `Scanner` instance is occupying a tiny amount of memory, which is entirely irrelevant. Further, the reference ceases to exist when the `main` method ends anyway. The actual reason why this object doesn’t get garbage collected, is that the garbage collector doesn’t even run in your program, as it has no reason to run. You won’t recognize this correctly, because as soon as you connect a monitoring tool to check this, the monitoring tool itself produces garbage and eventually causes the garbage collector to run. – Holger Feb 10 '20 at 08:38