ЭТО ДОЛЖНО БЫТЬ УСТАРЕЛО В JAVA 9!
Используйте java.util.Cleaner
вместо этого! (Или sun.misc.Cleaner
на более старой JRE)
Исходный пост:
Я обнаружил, что использование PhantomReferences имеет почти такое же количество подводных камней, что и методы финализатора (но меньше проблем, если вы все сделаете правильно). Я написал небольшое решение (очень небольшую структуру для использования PhantomReferences) для Java 8. Оно позволяет использовать лямбда-выражения в качестве обратных вызовов, запускаемых после удаления объекта. Вы можете зарегистрировать обратные вызовы для внутренних ресурсов, которые должны быть закрыты. Благодаря этому я нашел решение, которое мне подходит, поскольку делает его гораздо более практичным.
https://github.com/claudemartin/java-cleanup
Вот небольшой пример, показывающий, как регистрируется обратный вызов:
class Foo implements Cleanup {
public Foo() {
this.registerCleanup((value) -> {
try {
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
А есть еще более простой метод автоматического закрытия, который делает примерно то же, что и выше:
this.registerAutoClose(this.resource);
Чтобы ответить на ваши вопросы:
[тогда какая от этого польза]
Нельзя очистить то, чего не существует. Но у него могли быть ресурсы, которые все еще существуют и которые нужно очистить, чтобы их можно было удалить.
Но какова польза от этого понятия / класса?
Необязательно делать что-либо с каким-либо эффектом, кроме отладки / ведения журнала. А может для статистики. Мне это больше похоже на службу уведомлений от GC. Вы также можете использовать его для удаления агрегированных данных, которые становятся неактуальными после удаления объекта (но, вероятно, для этого есть лучшие решения). В примерах часто упоминается, что соединения с базой данных должны быть закрыты, но я не понимаю, почему это такая хорошая идея, поскольку вы не можете работать с транзакциями. Фреймворк приложения предоставит для этого гораздо лучшее решение.
Вы когда-нибудь использовали это в каком-либо из своих проектов или у вас есть какой-нибудь пример, где мы должны это использовать? Или эта концепция сделана только для собеседования;)
Я использую его в основном только для регистрации. Так что я могу отследить удаленные элементы и посмотреть, как работает сборщик мусора и как его можно настроить. Я бы не стал запускать таким образом критический код. Если что-то нужно закрыть, это следует сделать с помощью оператора try-with-resource-statement. И я использую его в модульных тестах, чтобы убедиться, что у меня нет утечек памяти. Так же, как это делает jontejj. Но мое решение более общее.