Когда вызывается finalize() во время сборки мусора?

От :

Q11 из https://www.baeldung.com/java-memory-management-interview-questions

Когда объект получает право на сборку мусора, сборщик мусора должен запустить для него finalize(); этот метод гарантированно запускается только один раз, поэтому сборщик помечает объект как завершенный и дает ему паузу до следующего цикла.

У меня есть несколько вопросов, чтобы задать:

  • Это утверждение верно?
  • На этапе маркировки сборщик мусора вызывает метод finalize()?
  • Почему он дает отдых до следующего цикла?

P.S: Я понимаю, что finalize() окончательно устарела в Java 9. Спасибо доброй душе, которая решила это сделать.


person Sara    schedule 23.12.2018    source источник
comment
Да, это правильно. Я забыл, насколько конкретна спецификация Java в отношении финализации, поэтому я не знаю, говорит ли она точно, какую фазу вызовет сборщик мусора finalize(), но подходит для сборки мусора — важный момент. Вот когда объект может finalize().   -  person markspace    schedule 23.12.2018
comment
@markspace Спецификация (JLS 12.6) ничего не говорит о фазах. Это деталь реализации.   -  person Andreas    schedule 23.12.2018


Ответы (1)


На этапе маркировки сборщик мусора вызывает метод finalize()?

Зависит от реализации, но обычно нет. Финализатор вызывается фоновым потоком после завершения сборки мусора.

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

Почему он дает отдых до следующего цикла?

На высоком уровне (упрощенном) он работает следующим образом (см. JLS 12.6.1 для терминов):

  • GC обнаруживает объекты, которые недоступны:

    • Если у объекта есть метод финализатора, добавьте его в очередь финализатора.
      Объект можно финализировать.

    • Если объект доступен из объекта finalizable, оставьте его.
      Объект доступен финализатору.

    • В противном случае освободите память сейчас.
      Объект был недоступен.

  • Поток фонового финализатора обрабатывает объекты, находящиеся в очереди finalizable:

    • Invokes finalize() method.
      When method returns, the object is finalized.
  • Поскольку сборка мусора уже завершена, завершенные объекты "отдыхают" до следующего цикла сборки мусора.

  • В следующем цикле сборки мусора объекты с методом финализатора, помеченным как finalized, рассматриваются как недоступные, и память будет освобождена (при условии, что метод финализатора не сделал объект доступен снова).

Обратите внимание, что может выполняться много циклов GC, пока объект находится в состоянии finalizable, т. е. потоку Finalizer может потребоваться некоторое время для обработки объекта.

person Andreas    schedule 23.12.2018
comment
На практике реализация не помечает объекты как «завершенные», а скорее помечает объекты, имеющие нетривиальный finalize(), как «незавершенные» при создании, чтобы снять пометку, когда они станут финализируемыми. Таким образом, сборщику мусора не нужно различать недостижимые объекты, не имеющие финализатора, и недостижимые объекты, финализатор которых уже запущен. Важно иметь в виду, что к моменту возврата метода finalize() объект может и не быть недостижимым (должен, но метод может содержать произвольный код). - person Holger; 07.01.2019