Java. Класс Object и его методы. Часть 6 — finalize

В первом посте мы рассматривали все методы класса Object. Методы wait, notify и notifyAll мы не будем рассматривать сейчас, так как они относятся к многопоточному программированию, так что вернемся к ним позже. Вкратце, эти методы нужны для управления объектами из разных потоков.

Итак, остается последний метод в классе Object и это метод finalize(), который отмечен мофидикатором protected и имеет пустое тело, которое может бросить исключение. Пустое тело явно указывает на необходимость переопределения в наследнике. Но зачастую этот метод крайне редко вызывают. Итак, зачем он ?

Прочитаем документацию.

Сборщик мусора вызывает этот метод когда на объект больше нет ссылок. В наследнике нужно переопределить, чтобы каким-нибудь добавочным методом освободить некие ресурсы, например поток чтения/записи. Если после вызова метода finalize() бросается непроверяемое исключение, то оно будет игнорировано! Также пишется в документации, что метод не будет вызван более одного раза.

Для начала давайте рассмотрим простой пример. Создаем простой класс с 1 полем и в методе finalize() пропишем вывод в консоль информацию по элементу.

Теперь давайте создадим миллион экземпляров и посмотрим сколько раз вызовется этот метод.

После запуска программы мы увидим в мониторе нечто подобное:

Несколько десятков тысяч объектов после индекса 360 000 начали подчищаться сборщиком мусора и несколько тысяч после индекса 720 000. Это означает лишь то, что сборщик мусора выполняет свою работу тогда, когда необходима память для новых объектов (т.е. свободная память забивается при создании порядка 350 000 объектов).

Именно поэтому полагаться на вызов метода finalize() не стоит, так как вы никогда не будете уверены когда JVM понадобится свободная память и когда сборщик мусора выполнит свою работу.

Давайте тогда создадим поток в конструкторе нового класса и попробуем его закрыть в методе finalize().

Как видим, из 900 случаев метод finalize() сработал всего 4 раза. Это значит что 896 потоков остались незакрытыми. Поэтому полагаться только на метод finalize() не рекомендуется. Он может служить как дополнительный метод, но не как основной и единственный для освобождения ресурсов. В сети советуют использовать вызов этого метода для долгих процессов, в ходе которых нельзя быть уверенным, что ресурсы освободились и еще раз попытаться закрыть их.

Теперь закроем поток в блоке finally и напишем дополнительное закрытие в методе finalize(). Также поставим счетчик и выведем в конце количество раз когда вызвался метод finalize();

Теперь вызовы метода finalize() участились.

p.s. число 900 было найдено чисто эмпирически, при меньших повторах результат не виден. Можете увеличить количество повторов и наблюдать за вызовами метода finalize().

p.p.s. Еще одна возможность метода finalize() получить доступ к недоступному полю.

====================================

result:

This is finalize

MyObject still alive!

=====================================

So you may make an unreachable instance reachable in finalize method.

Запись опубликована в рубрике Программирование Java. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *