Единственный надежный способ сделать это ... что я могу придумать ... это использовать обратные вызовы / слушатели;Например,
public MyClass
void myMethod(Function<MyClass, Void> onCompletion) {
try {
// Do stuff
} finally {
onCompletion.apply(this);
}
}
Вы также можете реализовать это, используя MethodHandles.tryFinally
, чтобы создать дескрипторы методов для вашего метода, которые реализуют обратный вызов, оборачивая методы.
Все, что основано на типах Reference
, неявно зависит от сборки мусора.Это будет дорого, и вы будете иметь небольшой контроль над получением уведомлений.
Есть ли альтернативный способ добиться этого?Например, некоторая маркировка JVM может поставить эту переменную, поскольку очевидно, что это локальный объект, который определенно является сборщиком мусора ...
AFAIK, нет, нет.И JVM / JIT не делают то, что вы предположили;то есть они не помечают «очевидный» локальный объект для финализации или сбора перед обычным циклом GC.
Почему бы и нет?Потому что это сделало бы приложения медленнее, если бы это произошло.Единственное преимущество заключается в том, что финализация / обработка ссылок может произойти раньше, но для хорошо написанного приложения это не имеет значения.Хорошо написанная программа не должна заботиться о , когда происходит завершение / обработка ссылок, так как время явно не гарантируется спецификациями.
И оказывается, что escape-анализ тоже не помогает:
Теперь я знаю, что JIT может корректировать таблицы, которые сообщают GC, что еще находится в области видимости (см. Комментарий Хольгера; например, finalize () вызывается для сильно достижимого объекта в Java 8 ).Но это не меняет последовательность инструкций метода.Только GC обращает внимание на эту информацию ... , пока GC работает .