Сборщик мусора и метод finalize

Author: Tatyana Milkina

Каждый раз при создании объекта под него выделяется память. Память не резиновая и когда-то она может окончиться. В некоторых языках программирования разработчики должны сами контролировать освобождение памяти. В Java же освобождение памяти выполняется автоматически. Используемая для выполнения этой задачи технология называется сборщиком мусора. Есть возможность запросить сборку мусора самим, для чего используется метод System.gc(). НО - JVM сама решит выполнять ли ваш запрос!

Сборка мусора проходит следующим образом: при отсутствии каких либо ссылок на объект программа заключает, что этот объект больше не нужен, и занимаемую объектом память можно освободить. 

Например, в методе main() класса Cup создается объект типа Cupна который указывает переменная cup. После выполнения строчки cup = nullобъект все еще существует в памяти, но на него не указывает ни одна ссылка. Этот объект является кандидатом для удаления при сборке мусора. Кроме того объект класса Cup содержит ссылочную переменную, указывающую на объект типа Spoon. Этот объект тоже будет удален сборщиком мусора.

public class Spoon {
}
public class Cup {
    Spoon spoon;

    Cup(Spoon spoon) {
        this.spoon = spoon;
    }

    public static void main(String[] args) {
        Cup cup = new Cup(new Spoon());
        cup = null;
     }
}

Если объект взаимодействует с какими-то ресурсами, например открывает поток вывода и читает из него, то такой поток необходимо закрыть перед удалением объекта из памяти. Для этого в языке Java достаточно переопределить метод finalize(), который вызывается в исполняющей среде Java непосредственно перед удалением объекта данного класса. В теле метода finalize() нужно указать те действия, которые должны быть выполнены перед уничтожением объекта. Метод finalize() вызывается лишь непосредственно перед сборкой "мусора".

Метод finalize() не вызывается при выходе объекта из области действия. Заранее неизвестно, когда будет (и будет ли вообще) выполняться метод finalize(). И самое главное - начиная с Java 9 этот метод не рекомендуется к использованию, а в Java 18 - deprecated for removal. Но все таки приведем пример его использования.

Добавим finalize() в классы Spoon и Cup, а также запросим вызвать сборщика мусора вызвав метод System.gc(), для того чтобы протестировать вызов finalize():

public class Spoon {
    @Override
    protected void finalize() {
        System.out.println("Ложка исчезает навсегда");
    }
}
public class Cup {
    private Spoon spoon;

    public Cup(Spoon spoon) {
        this.spoon = spoon;
    }

    @Override
    protected void finalize()  {
        System.out.println("Чашка исчезает навсегда");
    }

    public static void main(String[] args) {
        Cup cup = new Cup(new Spoon());
        cup = null;
        System.gc();
     }
}

Результат выполнения:

Ложка исчезает навсегда
Чашка исчезает навсегда
Читайте также:
Комментарии