PhantomReference с нулевой очередью

Java позволяет писать:

new PhantomReference(new Object(), null)

В этом случае будет собрано new Object()?

Насколько я понимаю, фантомная ссылка - это альтернатива использованию метода finalize().

И после появления ссылки в очереди, мне нужно сделать некоторые дополнительные действия, а затем запустить clear()

Java-документ остается:

Можно создать фантомную ссылку с нулевой очередью, но такая ссылка совершенно бесполезна: ее метод get всегда будет возвращать null и, поскольку у нее нет очереди, она никогда не будет поставлена ​​в очередь.

Что значит, если он никогда не будет поставлен в очередь?

Насколько я понимаю, это означает, что после вызова метода finalize ссылка не будет добавлена ​​в referenceQueue. Таким образом, это может привести к тому, что:
1. Память объекта будет очищена сразу
2. Память объекта не будет очищена

какой случай правильный?


person gstackoverflow    schedule 30.12.2016    source источник
comment
Каков ваш фактический вопрос здесь? Можете ли вы объяснить свою проблему более четко?   -  person UNIQUEorn    schedule 30.12.2016
comment
Вы смотрели на этот stackoverflow.com/questions/1599069/ например?   -  person GhostCat    schedule 30.12.2016
comment
И javadoc для этого ctor PhantomReference ясно говорит: Возможно создать фантомную ссылку с нулевой очередью, но такая ссылка совершенно бесполезна: ее метод get всегда будет возвращать null и, поскольку у него нет очереди , он никогда не будет поставлен в очередь. Итак, да, этот вновь созданный объект подвергается сборке мусора.   -  person GhostCat    schedule 30.12.2016
comment
@GhostCat, почему ты так думаешь? как мы можем это проверить? не вижу причинно-следственной связи   -  person gstackoverflow    schedule 30.12.2016
comment
Передача этого вновь созданного объекта X в PhantomReference... не должна делать X живым объектом. Нет никаких причин, по которым следует запрещать GC собирать его. И поскольку PhantomReference также не имеет очереди для X ... Я предполагаю, что единственное, что может случиться с X, это сборка мусора при следующем запуске GC. И я согласен с UNIQUEorn — понятия не имею, к чему вы хотите обратиться с этим вопросом. Какую проблему вы собираетесь решить?   -  person GhostCat    schedule 30.12.2016
comment
@GhostCat, но если мы передадим очередь в конструктор, очередь будет содержать ссылку, и это предотвратит сбор объекта?   -  person gstackoverflow    schedule 30.12.2016
comment
Нисколько. Ссылки ясно объясняют, что: PhantomRefernces не предотвращает сборку мусора. Это просто механизм понимания, когда сборщик мусора выполняет свою работу. Вы можете сказать: похлопайте меня по плечу, когда X уйдет. И тогда вы получаете похлопывание по плечу; и решить, что с этим делать. Вот и все.   -  person GhostCat    schedule 30.12.2016
comment
@GhostCat выглядит так, как будто это правильно для слабых/мягких ссылок, но неверно для фантомной ссылки   -  person gstackoverflow    schedule 30.12.2016
comment
И что заставляет вас так думать?   -  person GhostCat    schedule 30.12.2016
comment
@GhostCat docs.oracle.com/javase/ 7/docs/api/java/язык/ref/   -  person gstackoverflow    schedule 30.12.2016
comment
@GhostCat В отличие от мягких и слабых ссылок, фантомные ссылки не удаляются автоматически сборщиком мусора при постановке в очередь. Объект, доступный через фантомные ссылки, останется таковым до тех пор, пока все такие ссылки не будут очищены или сами не станут недоступными.   -  person gstackoverflow    schedule 30.12.2016
comment
@UNIQUEorn, я просто глубже изучаю/исследую Java   -  person gstackoverflow    schedule 30.12.2016
comment
ibm.com/developerworks/library/j-refs   -  person gstackoverflow    schedule 30.12.2016
comment
@gstackoverflow: эта статья IBM противоречит документации и фактическому поведению Oracle JRE в нескольких аспектах. Не рассчитывайте на это…   -  person Holger    schedule 11.01.2017
comment
@gstackoverflow: я заметил, что у вас есть несколько вопросов, связанных с gc, которые все еще открыты, например q1, q2, q3 и q4. Поэтому было бы здорово узнать, есть ли еще что-то неясное или эти вопросы уже не актуальны для вас. Я думаю добавить ответ здесь, тем более что он может противоречить большинству комментариев, но если он вам больше не нужен, вы можете вместо этого удалить вопрос.   -  person Holger    schedule 01.02.2017
comment
@Holger Буду рад, если вы ответите на эти вопросы   -  person gstackoverflow    schedule 01.02.2017
comment
@gstackoverflow: на другие вопросы есть ответы, на два из них даже есть мой ответ. Если они неудовлетворительны, вы должны добавить уточняющие комментарии, чтобы исправить то, чего не хватает. В противном случае вы можете принять ответ (не обязательно мой ;-). Я добавил ответ на этот вопрос; он стал немного больше, чем я думал, но это действительно интересная тема…   -  person Holger    schedule 01.02.2017
comment
@Holger Я увижу все ответы завтра.   -  person gstackoverflow    schedule 01.02.2017


Ответы (1)


Ну, как вы сами заметили, PhantomReference не очищается автоматически. Это означает, что пока вы сохраняете сильную ссылку на PhantomReference, референт будет оставаться фантомно доступным. Как сказано в документации: « Объект, доступный через фантомные ссылки, останется таковым до тех пор, пока все такие ссылки не будут очищены или сами не станут недоступными.

Однако рассмотрение ситуации, когда объект недоступен (сейчас я говорю о «самих фантомных ссылках»), может привести ко многим неожиданностям. Тем более, что очень вероятно, что эталонный объект, не обеспечивающий полезных операций, в дальнейшем трогать не будут.

Поскольку PhantomReference без очереди никогда не будет поставлен в очередь, а его метод get() всегда будет возвращать null, это действительно бесполезно.

Так почему же конструктор позволяет построить такой бесполезный объект? Ну, в документации самой первой версии (1.2) указано, что он выдаст NullPointerException, если очередь null. Это утверждение сохраняется до версии 1.4, затем Java 5 — это первая версия, содержащая утверждение о том, что вы можете создать PhantomReference без очереди, несмотря на то, что это бесполезно. Я предполагаю, что он всегда наследовал поведение суперкласса, разрешающее очередь null, что противоречило документации, и это было замечено так поздно, что было принято решение сохранить совместимость и адаптировать документацию, а не менять поведение.


Вопрос, на который еще труднее ответить, заключается в том, почему PhantomReference не очищается автоматически. В документации только говорится, что фантомный достижимый объект останется таковым, что является следствием того, что он не очищен, но не объясняет, почему это имеет какое-либо значение.

Этот вопрос был поднят на SO, но ответ на самом деле неудовлетворителен. В нем говорится «разрешить выполнение очистки до того, как объект будет удален сборщиком мусора», что может даже соответствовать мышлению того, кто принял это дизайнерское решение, но поскольку код очистки не может получить доступ к объекту, он не имеет релевантность независимо от того, выполняется ли он до или после восстановления объекта. Как сказано выше, поскольку это правило зависит от достижимости объекта PhantomReference, который подлежит оптимизации преобразований кода, может даже случиться так, что объект будет утилизирован вместе с экземпляром PhantomReference до завершения кода очистки, и никто этого не заметит.

Я также нашел аналогичный вопрос в рассылке для разработчиков HotSpot. list еще в 2013 году, на который также нет ответа.

Существует запрос на улучшение JDK-8071507, чтобы изменить это поведение и очистить PhantomReferences, как остальные, имеющие статус «исправлено» для Java 9, и действительно, в его документации теперь указано, что они очищаются, как и любая другая ссылка.

Это, к сожалению, подразумевает, что ответ в начале моего поста будет неверным, начиная с Java 9. Затем new PhantomReference(new Object(), null) сделает вновь созданный экземпляр Object немедленно доступным для сборки мусора, независимо от того, сохраняете ли вы сильную ссылку на экземпляр PhantomReference или нет.

person Holger    schedule 01.02.2017
comment
хорошее исследование. Таким образом, поскольку java 9 PhantomReference не будет дорабатывать альтернативу (потому что семантика перед очисткой) будет нарушена? а как насчет обратной совместимости? - person gstackoverflow; 02.02.2017
comment
Как я пытался сказать, семантика «до очистки» никогда не была бесполезной. Фантомная ссылка никогда не позволяет получить доступ к референту, следовательно, не имеет значения, существует ли референт еще в памяти или нет. Держать его в памяти дольше, чем необходимо, было пустой тратой ресурсов. Вот почему несколько приложений (включая мое) всегда использовали вместо этого WeakReference, что устраняет необходимость дважды собирать референт, что потенциально более эффективно. Для объектов без пользовательского метода finalize() нет семантической разницы. Начиная с Java 9 различий еще меньше. - person Holger; 02.02.2017