Ответ
Да, метод finalize() не гарантирован к вызову. Полагаться на него для критической логики (например, освобождения внешних ресурсов) — опасная практика.
Причины, по которым finalize() может не выполниться:
- Недетерминированность сборщика мусора (GC): JVM не гарантирует, когда будет запущен GC. Объект может никогда не быть собранным.
- Принудительное завершение программы: Вызов
System.exit(), аварийное завершение процесса (kill -9), ошибка в самой JVM. - Исключение в другом finalize(): Непойманное исключение, выброшенное в методе
finalize()какого-либо объекта, может прервать процесс финализации для оставшихся объектов. - Объект "воскрес" во время финализации: Если в методе
finalize()объект снова становится достижимым (например, присваивается статическому полю), он не будет собран, иfinalize()больше не вызовется для него.
Пример, демонстрирующий неопределенность:
public class FinalizeDemo {
@Override
protected void finalize() throws Throwable {
System.out.println("Finalize called for " + this);
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new FinalizeDemo(); // Создаем объекты без ссылок
}
// Подсказка GC, но не гарантия вызова finalize()
System.gc();
System.runFinalization(); // Еще одна попытка, также без гарантий
// Часто вывод в консоли пуст или содержит не все сообщения
}
}
Best Practice: Используйте блоки try-with-resources или явный вызов методов close() для управления ресурсами (реализуя AutoCloseable).