Сначала мы должны отметить, что это предложение было скопировано из документации для мягких и слабых ссылок на документацию для фантомных ссылок для Java 9, чтобы учесть изменения, сделанные в этой версии, но не подходит для фантомных ссылокпоэтому обоснование этого лучше объяснить для мягких и слабых ссылок.
Предположим, у вас есть следующая ситуация:
(weak)→ A
(weak)→ B (strong)→ A
технически, и A
, и B
слабо достижимы, но мы можем изменить это, вызывая метод get()
для любой слабой ссылки, чтобы получить сильную ссылку на его референт.
Когда мы делаем это для первой слабой ссылки, чтобы получить сильную ссылку на A
, объект B
останется слабо достижимым, но когда мы сделаем это, чтобы получить сильную ссылку на B
, объект A
также станет сильно достижимым из-за сильной ссылки от B
до A
.
Таким образом, у нас есть правило, что, если слабая ссылка на A
очищается,слабая ссылка на B
должна быть очищена, так как в противном случае можно было бы получить сильную ссылку на A
через B
, несмотря на то, что слабая ссылка на A
была очищена.И чтобы быть на безопасной стороне, это должно происходить атомарно, поэтому нет никакого возможного состояния гонки, позволяющего получить ссылку на B
между разрешением двух ссылок.
Как уже говорилось, это имеет меньшее значениедля фантомных ссылок, поскольку они не позволяют получить ссылку, но нет никаких оснований рассматривать их по-разному.
Дело здесь в том, что это не реальное бремя, учитывая, как на самом деле работают сборщики мусора.Они должны пересекать все живые ссылки, то есть сильно достижимые объекты, и все, что не встречается, является мусором на удаление.Таким образом, при обнаружении слабой ссылки во время обхода она не будет проходить референт, но помнит объект ссылки.После завершения обхода он будет проходить через все встреченные ссылочные объекты и посмотреть, был ли референт помечен как достижимый по другому пути.Если нет, эталонный объект очищается и связывается для постановки в очередь.
Для решения вашего примера:
(strong)→ A
(weak)→ B (strong)→ A
Здесь B
слабо достижимо независимо от строгой ссылки на A
,Когда вы устраняете сильную ссылку на A
, B
все еще слабо достижим и может быть поставлен в очередь.Формально, A
теперь слабо достижим, но JVM никогда не обнаружит это, не обнаружив, что B
тоже слабо достижимо.Единственный способ обнаружить, что A
является слабо достижимым, - это просмотреть контрольный граф, начиная с слабо достижимого B
.Но никакая реализация не делает этого.Сборщик мусора просто очистит слабую ссылку на B
и все.