As has already been answered, it is possible to execute code, and in particular to call functions, after catching a StackOverflowError
because the normal exception handling procedure of the JVM unwinds the stack between the throw
and the catch
points, freeing stack-space for you to use. And your experiment confirms that is the case.
However, that is not quite the same as saying that it is, in general, possible to recover from a StackOverflowError
.
A StackOverflowError
IS-A VirtualMachineError
, which IS-AN Error
. As you point out, Java provides some vague advice for an Error
:
indicates serious problems that a reasonable application should not try to catch
and you, reasonably, conclude that should sounds like catching an Error
might be OK in some circumstances. Note that performing one experiment does not demonstrate that something is, in general, safe to do. Only the rules of the Java language and the specifications of the classes you use can do that. A VirtualMachineError
is a special class of exception, because the Java Language Specification and the Java Virtual Machine Specification provide information about the semantics of this exception. In particular, the latter says:
A Java Virtual Machine implementation throws an object that is an instance of a subclass of the class VirtualMethodError
when an internal error or resource limitation prevents it from implementing the semantics described in this chapter. This specification cannot predict where internal errors or resource limitations may be encountered and does not mandate precisely when they can be reported. Thus, any of the VirtualMethodError
subclasses defined below may be thrown at any time during the operation of the Java Virtual Machine:
...
StackOverflowError
: The Java Virtual Machine implementation has run out of stack space for a thread, typically because the thread is doing an unbounded number of recursive invocations as a result of a fault in the executing program.
The crucial problem is that you "cannot predict" where or when a StackOverflowError
will be thrown. There are no guarantees about where it will not be thrown. You can not rely on it being thrown on entry to a method, for example. It could be thrown at a point within a method.
This unpredictability is potentially disastrous. As it can be thrown within a method, it could be thrown part way through a sequence of operations that the class considers to be one "atomic" operation, leaving the object in a partially modified, inconsistent, state. With the object in an inconsistent state, any attempt to use that object could result in erroneous behaviour. In all practical cases you can not know which object is in an inconsistent state, so you have to assume that no objects are trustworthy. Any recovery operation or attempt to continue after the exception is caught could therefore have erroneous behaviour. The only safe thing to do is therefore to not catch a StackOverflowError
, but rather to allow the program to terminate. (In practice you might attempt to do some error logging to assist troubleshooting, but you can not rely on that logging operating correctly). That is, you can not reliably recover from a StackOverflowError
.