как я могу изменить код, чтобы сборщик мусора удалил этот экземпляр из-за программы?

В строке, которую я пометил //D, есть одноразовое использование с экземпляром объекта Scanner. но его память останется в куче, пока программа играет (что навсегда). почему сборщик мусора не удалит этот объект экземпляра? как я могу изменить код, чтобы сборщик мусора удалил этот экземпляр из-за программы? спасибо

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

person Lorin Sherry    schedule 09.02.2020    source источник
comment
Как вы определяете, что Scanner остается в памяти? Вы уверены, что сборщик мусора запущен?   -  person Slaw    schedule 09.02.2020
comment
У вас есть два ответа на ваш вопрос, но что вам нужно знать: вряд ли когда-либо будет смысл делать то, о чем вы просили. Иногда вам нужно убедиться, что что-то собрано как можно скорее, но это случается, может быть, раз в год...   -  person maaartinus    schedule 10.02.2020


Ответы (2)


Вы можете удалить ссылку на сканер, установив для нее значение null, т.е. sc = null.

-OR-

Если вам больше не нужен Scanner, вы можете закрыть его после использования:

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

Еще лучше использовать try-with-resources следующим образом:

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

Обратите внимание, что sc.close() закрывает сканер и освобождает ресурс, а sc = null удаляет ссылку на сканер, но ресурс может оставаться открытым.

Предупреждение. Никогда не закрывайте Scanner для System.in, если он все еще нужен для дополнительных входных данных от System.in, так как закрытие Scanner также закроет System.in. Рассмотрим следующий код:

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

Попытка выполнить приведенный выше код приведет к:

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)
person Arvind Kumar Avinash    schedule 09.02.2020
comment
Спасибо! теперь вопрос что лучше? в СК = ноль; или к sc.close(); ? - person Lorin Sherry; 09.02.2020
comment
Вы почти никогда не захотите закрывать Scanner, который использует System.in в качестве источника данных, так как это также закроет System.in. - person Slaw; 09.02.2020
comment
@Slaw я запутался :\ - person Lorin Sherry; 10.02.2020
comment
@LorinSherry вы не должны делать ни того, ни другого, так как этот единственный экземпляр Scanner занимает крошечный объем памяти, что совершенно не имеет значения. Кроме того, ссылка перестает существовать, когда метод main все равно завершается. Фактическая причина, по которой этот объект не подвергается сборке мусора, заключается в том, что сборщик мусора даже не запускается в вашей программе, поскольку ему незачем запускаться. Вы не распознаете это правильно, потому что как только вы подключите инструмент мониторинга, чтобы проверить это, инструмент мониторинга сам производит мусор и в конечном итоге вызывает запуск сборщика мусора. - person Holger; 10.02.2020

как я могу изменить код, чтобы сборщик мусора удалил этот экземпляр из-за программы?

Вы должны установить значение объекта в null. Затем сборщик мусора освободит память кучи, используемую этим объектом.

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

Причина, по которой он не удаляется автоматически в конце метода, заключается в том, что вы инициализируете его в основном методе. Другими словами: основной метод останавливается, когда останавливается приложение.

person apt-get_install_skill    schedule 09.02.2020
comment
спасибо, а по какой причине сборщик мусора не удаляет его? - person Lorin Sherry; 09.02.2020
comment
Сборщик мусора не удалит все экземпляры, которые могут вам понадобиться через 10 строк кода. Вы должны явно указать GC сделать это. - person apt-get_install_skill; 09.02.2020
comment
Ознакомьтесь с этой статьей о GC geeksforgeeks.org/garbage-collection-java. - person apt-get_install_skill; 09.02.2020