Ну, как вы сами заметили, PhantomReference
не очищается автоматически. Это означает, что пока вы сохраняете сильную ссылку на PhantomReference
, референт будет оставаться фантомно доступным. Как сказано в документации: « Объект, доступный через фантомные ссылки, останется таковым до тех пор, пока все такие ссылки не будут очищены или сами не станут недоступными.”
Однако рассмотрение ситуации, когда объект недоступен (сейчас я говорю о «самих фантомных ссылках»), может привести ко многим неожиданностям. Тем более, что очень вероятно, что эталонный объект, не обеспечивающий полезных операций, в дальнейшем трогать не будут.
Поскольку PhantomReference
без очереди никогда не будет поставлен в очередь, а его метод get()
всегда будет возвращать null
, это действительно бесполезно.
Так почему же конструктор позволяет построить такой бесполезный объект? Ну, в документации самой первой версии (1.2) указано, что он выдаст NullPointerException
, если очередь null
. Это утверждение сохраняется до версии 1.4, затем Java 5 — это первая версия, содержащая утверждение о том, что вы можете создать PhantomReference
без очереди, несмотря на то, что это бесполезно. Я предполагаю, что он всегда наследовал поведение суперкласса, разрешающее очередь null
, что противоречило документации, и это было замечено так поздно, что было принято решение сохранить совместимость и адаптировать документацию, а не менять поведение.
Вопрос, на который еще труднее ответить, заключается в том, почему PhantomReference
не очищается автоматически. В документации только говорится, что фантомный достижимый объект останется таковым, что является следствием того, что он не очищен, но не объясняет, почему это имеет какое-либо значение.
Этот вопрос был поднят на SO, но ответ на самом деле неудовлетворителен. В нем говорится «разрешить выполнение очистки до того, как объект будет удален сборщиком мусора», что может даже соответствовать мышлению того, кто принял это дизайнерское решение, но поскольку код очистки не может получить доступ к объекту, он не имеет релевантность независимо от того, выполняется ли он до или после восстановления объекта. Как сказано выше, поскольку это правило зависит от достижимости объекта PhantomReference
, который подлежит оптимизации преобразований кода, может даже случиться так, что объект будет утилизирован вместе с экземпляром PhantomReference
до завершения кода очистки, и никто этого не заметит.
Я также нашел аналогичный вопрос в рассылке для разработчиков HotSpot. list еще в 2013 году, на который также нет ответа.
Существует запрос на улучшение JDK-8071507, чтобы изменить это поведение и очистить PhantomReference
s, как остальные, имеющие статус «исправлено» для Java 9, и действительно, в его документации теперь указано, что они очищаются, как и любая другая ссылка.
Это, к сожалению, подразумевает, что ответ в начале моего поста будет неверным, начиная с Java 9. Затем new PhantomReference(new Object(), null)
сделает вновь созданный экземпляр Object
немедленно доступным для сборки мусора, независимо от того, сохраняете ли вы сильную ссылку на экземпляр PhantomReference
или нет.
person
Holger
schedule
01.02.2017