Как определить, когда на объект больше не ссылаются - PullRequest
9 голосов
/ 16 октября 2008

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

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

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

Ответы [ 7 ]

13 голосов
/ 16 октября 2008

Короче говоря, нет.

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

4 голосов
/ 17 октября 2008

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

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

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

4 голосов
/ 16 октября 2008

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

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

2 голосов
/ 16 октября 2008

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

См. Мой ответ Зачем вам реализовывать finalize ()?

2 голосов
/ 16 октября 2008

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

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

0 голосов
/ 16 октября 2008

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

0 голосов
/ 16 октября 2008

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

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

...