Удаление обьектов в Java

Рейтинг: 2Ответов: 1Опубликовано: 14.12.2014

Появился вопрос об удалении объектов в Java. Ниже приведен пример из книги "Философия Java" Брюса Эккеля.

public class FinalizeObject {

    private static class Book {
        boolean checked = false;

        Book(boolean c) {
            checked = c;
        }

        void checkIn() {
            checked = false;
        }

        @Override
        protected void finalize() {
            if (checked)
                System.out.println("CheckedOut");
        }
    }

    public static void main(String[] args) {
        Book novel = new Book(true);
        novel.checkIn();
        new Book(true);
        new Book(true);
        System.gc();
    }
}

В результате запуска этого примера я получил такие выводы:

Запуск №1

CheckedOut
CheckedOut

Process finished with exit code 0

Запуск №2

CheckedOut
CheckedOut

Process finished with exit code 0

Запуск №3

Process finished with exit code 0

Когда после 3-го запуска я не увидел сообщения о вызове метода finalize(), сначала я подумал, что не попал просто по клавишам, но, проделав еще несколько запусков, я убедился, что метод действительно иногда не вызывается. Погуглив, я прочитал о том, что finalize() может действительно не вызываться при первом запуске GC.

Тогда у меня вопрос. Удалятся ли вообще когда-нибудь такие объекты, кроме случая остановки JVM?

Ответы

▲ 2Принят

Смотрите.

Объекты удаляются лишь тогда, когда garbage collector решит, что их нужно удалить (плюс на них не должно быть сильных ссылок). Это потому, что garbage collector занимается лишь выделением/освобождением памяти, и ничем другим. Если garbage collector решит, что с удалением можно подождать, он не удалит объект. В частности, если garbage collector узнает, что программа собирается закончиться, он скорее всего откажется от сборки мусора, т. к. память всё равно никому не будет нужна с завершением процесса.

Поэтому надеяться на вызов финализатора при сборке мусора вы не можете. Соответственно, располагать логику «подчистки» в финализаторе тоже не стоит.

Если вы хотите обеспечить гарантированную «подчистку» в предсказуемый момент, пользуйтесь интерфейсом Closeable/AutoCloseable, и по возможности конструкцией try-with-resources (или явным вызовом close()).