Как определить, когда на объект больше не ссылаются

StackOverflow https://stackoverflow.com/questions/208562

  •  03-07-2019
  •  | 
  •  

Вопрос

Есть ли способ создать обработчик регистрации, который будет вызываться ровно в тот момент, когда будет выпущена последняя ссылка на определенный объект?

Примером может служить объект, поддерживаемый физическим файлом данных, и как только на объект перестанут ссылаться, файл следует закрыть, а затем переименовать.Было бы неплохо, если бы это было возможно без явного вызова метода закрытия для этого объекта.

Все известные мне механизмы уведомления из эталонной области Weak/Phantom только утверждают, что уведомление произойдет в какой-то момент времени, но нет никакой гарантии, когда это произойдет...

Это было полезно?

Решение

Суммируя, нет.

Спецификация Java явно запрещает вам знать, когда выпущена последняя ссылка.От этого зависят реализации (и оптимизации) JVM.Крюка нет.

Другие советы

Насколько я понимаю, и я некоторое время искал «деструктор» для объектов Java, невозможно узнать, когда вы потеряете последнюю ссылку.Java отслеживает ссылки на объекты, но из соображений производительности обновляет эту информацию только во время сборки мусора.

Ближе всего — метод Finalize, который следует вызывать во время сборки мусора, но нет никакой гарантии, что он будет вызван даже тогда.

Я думаю, что WeakReference делает то, что вы хотите.WeakReference помещается в ReferenceQueue, как только он становится слабо достижимым (т.все сильные ссылки исчезли).

См. эту статью автора Итан Николас.

Если вы беспокоитесь о том, что некоторые ссылки не достигают ReferenceQueue при завершении работы, сохраните список всех созданных объектов (используя WeakReferences или PhantomReferences).Добавьте перехватчик завершения работы, который проверяет список на наличие невыполненных ссылок и выполняет любые необходимые действия.

Проблема в том, «Как это реализовать без чего-то, содержащего ссылку на объект?»

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

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

Смотрите мой ответ Зачем вам вообще реализовывать метод Finalize()?

Это невозможно сделать с помощью Java - насколько я могу судить, ему нужен сборщик мусора с подсчетом ссылок.Рассматривали ли вы возможность открывать и закрывать файл физических данных вашего объекта по мере необходимости вместо того, чтобы держать его открытым в течение всего времени существования объекта?

Ты мог переопределить finalize() в вашем объекте, но это проблематично по причинам, упомянутым другими.

Для вашего конкретного примера вы можете взглянуть на использование чего-то вроде File.deleteOnExit(), который удалит файл после выхода из виртуальной машины.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top