PhantomReference с нулевой очередью
Java позволяет писать:
new PhantomReference(new Object(), null)
В этом случае new Object()
будет собираться?
Как я понимаю, фантомная ссылка является альтернативой finalize()
использование метода.
И после появления ссылки в очереди, мне нужно сделать некоторые дополнительные действия, а затем запустить clear()
Ява Док остается:
Можно создать фантомную ссылку с нулевой очередью, но такая ссылка совершенно бесполезна: ее метод get всегда будет возвращать ноль и, поскольку у него нет очереди, он никогда не будет помещен в очередь.
Что значит, если он никогда не будет поставлен в очередь?
Как я понимаю, это означает, что после финализации вызов метода не будет добавлен в referenceQueue. Таким образом, это может привести к:
1. память объекта будет очищена сразу
2. Память объекта не будет очищена
какой случай правильный?
1 ответ
Ну, как вы заметили, PhantomReference
не очищается автоматически Это подразумевает, что до тех пор, пока вы сохраняете сильную ссылку на PhantomReference
референт останется призрачным. Как сказано в документации: "Объект, доступный через фантомные ссылки, будет оставаться таковым до тех пор, пока все такие ссылки не будут очищены или сами станут недоступными."
Однако рассмотрение того, когда объект недоступен (сейчас я говорю о "самих фантомных ссылках"), может привести ко многим сюрпризам. Тем более, что весьма вероятно, что эталонный объект, не обеспечивающий полезных операций, больше не будет затронут.
Так как PhantomReference
без очереди никогда не будет поставлен в очередь и его get()
метод всегда вернет null
, это действительно не полезно.
Так почему же конструктор позволяет построить такой бесполезный объект? Ну, документация самой первой версии (1.2) гласит, что NullPointerException
если очередь null
, Это утверждение сохраняется до 1.4, тогда Java 5 является первой версией, содержащей утверждение, что вы можете построить PhantomReference
без очереди, хотя и бесполезны. Я предполагаю, что он всегда наследовал поведение суперкласса null
очереди, противоречащей документации, и это было замечено настолько поздно, что было принято решение оставаться совместимым и адаптировать документацию, а не менять поведение.
Еще труднее ответить на вопрос, почему PhantomReference
не очищается автоматически Документация только говорит, что объект, достижимый фантомом, останется таким, что является следствием того, что его не очистили, но не объясняет, почему это имеет какое-либо значение.
Этот вопрос был задан на SO, но ответ на самом деле не удовлетворяет. В нем говорится "разрешить выполнение очистки перед сборкой мусора", что может даже соответствовать мышлению любого, кто принял это проектное решение, но поскольку код очистки не может получить доступ к объекту, он не имеет никакого отношения к тому, выполняется ли он до или после того, как объект восстановлен. Как сказано выше, так как это правило зависит от достижимости PhantomReference
объект, который подлежит оптимизации преобразования кода, может быть даже тот случай, когда объект восстанавливается вместе с PhantomReference
экземпляр до завершения кода очистки, никто не заметил.
Я также нашел аналогичный вопрос в списке рассылки разработчиков HotSpot еще в 2013 году, на который также нет ответа.
Существует запрос на улучшение JDK-8071507, чтобы изменить это поведение и очистить PhantomReference
Так же, как и другие, которые имеют статус "фиксированный" для Java 9, и, действительно, в его документации теперь говорится, что они очищаются, как и любая другая ссылка.
Это, к сожалению, подразумевает, что ответ в начале моего поста будет неправильным, начиная с Java 9. Затем, new PhantomReference(new Object(), null)
сделает вновь созданный Object
экземпляр, имеющий право на сборку мусора, независимо от того, сохраняете ли вы строгую ссылку на PhantomReference
экземпляр или нет.