Как уже было сказано, после перехвата a можно выполнять код и, в частности, вызывать функции, StackOverflowError
поскольку обычная процедура обработки исключений JVM раскручивает стек между точками throw
и catch
точками, освобождая пространство стека для использования. И ваш эксперимент подтверждает это.
Однако, это не совсем то же самое , как сказать , что это, в общем, можно восстановить из StackOverflowError
.
StackOverflowError
IS-A VirtualMachineError
, который IS-AN Error
. Как вы отметили, Java дает несколько расплывчатых советов для Error
:
указывает на серьезные проблемы, которые разумное приложение не должно пытаться уловить
и вы, резонно заключить , что должно звучит как ловить Error
может быть хорошо в некоторых обстоятельствах. Обратите внимание, что выполнение одного эксперимента не демонстрирует, что что-то в целом безопасно. Это могут сделать только правила языка Java и спецификации используемых вами классов. A VirtualMachineError
- это особый класс исключения, поскольку спецификация языка Java и спецификация виртуальной машины Java предоставляют информацию о семантике этого исключения. В частности, последний говорит :
Реализация виртуальной машины Java создает объект, являющийся экземпляром подкласса класса, VirtualMethodError
когда внутренняя ошибка или ограничение ресурсов не позволяют реализовать семантику, описанную в этой главе. Эта спецификация не может предсказать, где могут возникнуть внутренние ошибки или ограничения ресурсов, и не требует точного определения того, когда о них можно сообщить. Таким образом, любой из VirtualMethodError
подклассов, определенных ниже, может быть запущен в любое время во время работы виртуальной машины Java:
...
StackOverflowError
: Реализация виртуальной машины Java исчерпала пространство стека для потока, как правило, из-за того, что поток выполняет неограниченное количество рекурсивных вызовов в результате ошибки в выполняющейся программе.
Ключевой проблемой является то, что вы «не можете предсказать», где и когда StackOverflowError
будет брошен. Нет никаких гарантий, куда он не будет брошен. Например, вы не можете полагаться на то, что он будет брошен при входе в метод. Его можно бросить в точку внутри метода.
Эта непредсказуемость потенциально губительна. Поскольку он может быть брошен внутри метода, он может быть брошен частично через последовательность операций, которые класс считает одной «атомарной» операцией, оставляя объект в частично измененном, несовместимом состоянии. Когда объект находится в несовместимом состоянии, любая попытка использовать этот объект может привести к ошибочному поведению. Во всех практических случаях вы не можете знать, какой объект находится в несогласованном состоянии, поэтому вы должны предположить, что ни один объект не заслуживает доверия. Следовательно, любая операция восстановления или попытка продолжить после обнаружения исключения могут иметь ошибочное поведение. Поэтому единственное безопасное решение - не пойматьStackOverflowError
, а скорее позволить программе завершить работу. (На практике вы можете попытаться вести журнал ошибок, чтобы помочь в устранении неполадок, но вы не можете полагаться на правильную работу этого журнала). То есть из файлаStackOverflowError
.