Як уже було сказано , можна виконати код і, зокрема, викликати функції, після StackOverflowError
вилучення a, тому що звичайна процедура обробки винятків 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 Virtual Machine не вистачає місця для стеку для потоку, як правило, через те, що потік виконує необмежену кількість рекурсивних викликів внаслідок помилки у виконанні програми.
Найважливішою проблемою є те, що ви "не можете передбачити", де або коли StackOverflowError
буде кинуто повідомлення. Немає гарантій щодо того, куди його не кинуть. Ви не можете розраховувати на те, що він буде кинутий при вступі до методу, наприклад. Це може бути кинуто в точку в рамках методу.
Ця непередбачуваність потенційно згубна. Оскільки це може бути кинуто у межах методу, його можна перекинути частиною через послідовність операцій, які клас вважає однією "атомною" операцією, залишаючи об'єкт у частково модифікованому, непослідовному стані. Якщо об'єкт знаходиться в непослідовному стані, будь-яка спроба використання цього об'єкта може спричинити помилкову поведінку. У всіх практичних випадках ви не можете знати, який об’єкт знаходиться в непослідовному стані, тому ви повинні припустити, що жоден об’єкт не є надійним. Отже, будь-яка операція відновлення або спроба продовження після вилучення винятку може мати помилкову поведінку. Тому єдине безпечне, що потрібно зробити, це не зловити aStackOverflowError
, а скоріше, щоб дозволити програмі припинити роботу. (На практиці ви можете спробувати зробити деякий журнал помилок, щоб полегшити усунення несправностей, але ви не можете розраховувати на те, що журнал працює правильно). Тобто ви не можете надійно відновитись із aStackOverflowError
.