Короткий ответ
Да, такое возможно. Блок finally не выполнится, если JVM завершается до выхода из try — при вызове System.exit() или аварийном завершении (сбой JVM, OutOfMemoryError, kill процесса), — либо если поток застревает внутри try (бесконечный цикл, вечное ожидание на мониторе) и просто не доходит до блока.
Как это работает подробнее
finally гарантированно выполняется при обычном завершении try, при исключении и даже перед return — управление передаётся в finally до выхода из метода. Это ключевая гарантия языка. Блок не выполняется только тогда, когда завершается сама JVM или поток не может выйти из try.
- System.exit() — завершает виртуальную машину, выполнение до
finallyне доходит. - Аварийное завершение — сбой JVM, критическая ошибка вроде
OutOfMemoryError, принудительное завершение процесса (kill). - Застревание потока — бесконечный цикл или вечное ожидание на мониторе внутри
try: код не доходит доfinally; в старых версиях к этому приводила и принудительная остановка потокаThread.stop().
Пример кода
FinallyDemo.java
public class FinallyDemo {
public static void main(String[] args) {
try {
System.out.println("Внутри try");
System.exit(0); // JVM завершается до finally
} finally {
System.out.println("finally: не будет напечатано");
}
}
}Что использовать на практике
- Не рассчитывайте на
finallyпри вызовеSystem.exit()— он не выполнится; для действий при завершении JVM используйте shutdown hook. finallyприменяйте для освобождения ресурсов и сброса состояния: обычный поток управления гарантирует его выполнение.
Подводные камни
returnи исключение блокfinallyне отменяют — он выполнится перед выходом из метода.System.exit()и аварийное завершение процесса «обходят»finally— cleanup там не спасёт.- Значение, возвращаемое из
finally, перекрываетreturnизtry— источник трудноуловимых багов.
Как отвечать на собеседовании
- Каркас: ответьте «да, возможно» → перечислите случаи:
System.exit(), аварийное завершение JVM/процесса, застревание или остановка потока → подчеркните, что обычныеreturnи исключенияfinallyне отменяют → завершите примером проSystem.exit().