В каких случаях блок finally не выполняется в Java
Что проверяют
Знаете ли вы редкие исключения из правила и понимаете ли, почему return в finally опасен.
Как отвечать
Обычно finally выполняется всегда: и при нормальном выходе, и при return, и при break, и при исключении. Не выполнится он в считанных случаях:
System.exit()внутриtry: виртуальная машина завершается немедленно, отложенных действий не остаётся;- аварийное завершение процесса:
kill -9, падение самой машины,Runtime.halt(); - поток никогда не доходит до конца блока: бесконечный цикл, вечная блокировка, ожидание, из которого нет выхода. Формально
finallyне отменён, просто до него не доходит очередь; - поток-демон остановлен завершением программы: обычные потоки не дают приложению закрыться, демоны нет;
- тяжёлая ошибка: при
StackOverflowErrorможет не хватить стека на выполнение блока, приOutOfMemoryErrorвнутри блока может не хватить памяти; Thread.stop(): метод давно объявлен устаревшим и удалён, но в старом коде встречается.
Дальше стоит сразу перейти к тому, ради чего вопрос обычно и задают: finally не должен возвращать значение и бросать исключение.
try {
throw new IllegalStateException("настоящая ошибка");
} finally {
return 1; // исключение бесследно исчезает
}return в finally перекрывает и возврат из try, и летящее исключение, из-за чего сбой пропадает молча. То же с break и continue. Компилятор обычно предупреждает, и это предупреждение подавлять нельзя.
Полезное дополнение: для закрытия ресурсов вместо finally берут try-with-resources, там проблема потерянного исключения решена через подавленные исключения.
Где спотыкаются
Называют обычное исключение причиной невыполнения блока.
Пишут return в finally и теряют ошибки.
Не знают про System.exit.
Закрывают ресурсы вручную в finally вместо try-with-resources.