Когда создается объект с нетривиальным методом finalize()
, JVM создаст Finalizer
(FinalReference
) с этим объектом в качестве референта. Что произойдет, если этот объект также будет обернут Soft/Weak или Phantom Reference? Попытается ли GC сначала поставить в очередь Finalizer
(вызов метода finalize для него), а затем поставить в очередь другую ссылку или наоборот?
Какая ссылка Finalizer (FinalReference) или Weak/Phantom/Soft Reference имеет более высокий приоритет для GC
Ответы (1)
Я думаю, ваш вопрос не о времени постановки в очередь, на самом деле.
Обратите внимание на раздел Уведомление документа документация пакета
Через некоторое время после того, как сборщик мусора определит, что достижимость референта изменилась на значение, соответствующее типу ссылки, он добавит ссылку в соответствующую очередь.
(Обратите внимание на «некоторое время спустя»)
и аналогично, все ссылочные типы имеют выражение вида:
Предположим, что сборщик мусора определяет в определенный момент времени, что объект слабо достижим. В это время он атомарно удалит все слабые ссылки на этот объект и все слабые ссылки на любые другие слабо достижимые объекты, из которых этот объект доступен через цепочку сильных и мягких ссылок. В то же время он объявит все ранее слабо достижимые объекты финализируемыми. В то же время или позже он поставит в очередь те недавно очищенные слабые ссылки, которые зарегистрированы в очередях ссылок.
(взято из WeakReference
; Обратите внимание на «в то же время или позже»)
На практике сборщик мусора передает обнаруженные ссылки другому потоку, который ставит их в очередь асинхронно. Поскольку неуказанная задержка делает порядок, в котором приложение будет извлекать ссылки из очереди, недетерминированным, бессмысленно спрашивать здесь о порядке.
Однако, я полагаю, вас на самом деле интересует другой «определенный момент времени», когда «сборщик мусора определяет, что достижимость референта изменилась на значение, соответствующее тип ссылки» и решит атомарно очистить ссылки и сделать их подходящими для постановки в очередь.
Когда имеется смесь нескольких объектов ссылок с разными типами, включая ссылку Finalizer
, но нет строгой ссылки, возможны два сценария:
- Есть по крайней мере одна мягкая ссылка и нет давления памяти. Затем сборщик мусора может решить, что нет очистки соответственно. поставить в очередь любую ссылку.
- Мягкая ссылка отсутствует или сборщик мусора решает, что нехватка памяти оправдывает очистку мягких ссылок. Затем все мягкие и слабые ссылки очищаются, и все мягкие, слабые ссылки и ссылки финализатора передаются для постановки в очередь.
Только фантомные ссылки остаются нетронутыми.
Обратите внимание, что после начала финализации ссылки Finalizer
больше нет, но во время финализации может быть создана новая мягкая или слабая ссылка. Таким образом, результирующие сценарии такие же, как и при оптимизированной обработке объектов с помощью тривиального метода finalize()
. Может быть смесь мягких, слабых и фантомных ссылок без ссылки Finalizer
. Когда сильной ссылки не осталось, у нас снова есть два возможных сценария:
- Есть по крайней мере одна мягкая ссылка и нет давления памяти. Затем сборщик мусора может решить, что нет очистки соответственно. поставить в очередь любую ссылку.
- Мягкая ссылка отсутствует или сборщик мусора решает, что нехватка памяти оправдывает очистку мягких ссылок. Затем все мягкие, слабые и фантомные ссылки очищаютсяA, и все мягкие, слабые и фантомные ссылки передаются для постановки в очередь.
A фантомные ссылки очищаются в Java 9 или более поздней версии. В предыдущих версиях они только ставились в очередь без очистки.
Finalizer
ссылочный объект последовательно блокирует Phantom
ссылочный объект от постановки в очередь. Таким образом, объект со смесью ссылок Finalizer
и Phantom
потребует не менее 3 циклов сборки мусора (первый - поставить в очередь финализатора, второй - поставить в фантомную очередь, третий - удалить из кучи) для удаления из куча. Я прав?
- person Martin; 23.10.2019
Remark
, поэтому давайте рассмотрим Старый объект со смесью ссылок Finalizer
и Phantom
. GC выполнит: 1-й цикл — поставит в очередь ссылку Final
2-й цикл — очистит и поставит в очередь ссылку Phantom
(во время фазы Remark
) 3-й цикл — (вероятно, Mixed
цикл GC) освободит память.
- person Martin; 24.10.2019
Remark
фазе, поэтому в этом случае GC потребуется не менее 3 циклов GC (2 Concurrent Mark
цикла и 1 Mixed GC
цикл) для восстановления объем памяти. В любом случае, спасибо за такие хорошие ответы!
- person Martin; 24.10.2019
GC(0) Pause Young (Normal) (G1 Evacuation Pause)
, за которым следует GC(0) Skipped phase1 of Reference Processing...
, тот факт, что в моей программе нет слабых ссылок на процесс, не имеет значения. Дело в том, что эти журналы отображаются под young pause
, где также обрабатываются ссылки, а не только Remark
. Фактически, они должны обрабатываться везде, где есть приостановленная фаза. Некоторые GC (Shenandoah
) также могут выполнять большую часть обработки на этапе concurrent,
- person Eugene; 12.03.2020
referent
, а не reference
(это немного сложнее, но идея такова). Из-за этого он может обрабатывать некоторые типы слабых ссылок (при некоторых условиях) в фазе concurrent.
- person Eugene; 12.03.2020
finalize()
. Есть много вопросов и ответов по этому поводу – вот один – и освещение в книгах (например, «Essential Java» Джошуа Блоха). - person kaan   schedule 04.10.2019finalize()
. - person Martin   schedule 04.10.2019