Facts
- The Java SE API says about the
Errortype that it "indicates serious problems that a reasonable application should not try to catch"; also "errors are abnormal conditions that should never occur". - The JLS 11.1.3 "Asynchronous Exceptions" says about
VirtualMachineErrorthat it is an "internal error or resource limitation in the Java Virtual Machine that prevents it from implementing the semantics of the Java programming language".
Interpretation
Not only the spec explicitly recommends not to catch Errors, but also says that if VirtualMachineError happens, then there are no guarantees that the language semantics stands. It appears that the arguments against the Thread.stop/ThreadDeath can also be applied to at the very least any VirtualMachineError. Due to lazy resolution being allowed, the same is true for LinkageError: no code expects it or guards against it, so when it happens, it may result in corrupting the state of an object just like ThreadDeath or VirtualMachineError.
The above seems (to me) enough to decide that there is no robust way to handle Errors. The only way out I see is to have a Thread.UncaughtExceptionHandler that calls System.exit/Runtime.halt and maybe tries logging the Error before terminating the VM (a logging attempt may simply fail with another Error caused by the original one, which is especially obvious if the original Error is an OutOfMemoryError).
Questions
- Given that an
Errorrepresents an abnormal condition that should never occur and that applications should not try to catch it, what are the good reasons to expose theErrortype at all in Java SE API instead of handling errors always by terminating the VM without exposing them to applications? - Why do (almost?) all callback methods in the Java SE API, e.g.,
java.nio.channels.CompletionHandler.failed,CompletionStage.exceptionally,Flow.Subscriber.onError, acceptThrowable, which includesError, instead of acceptingException? Effectively, a callback that acceptsThrowableis not better than code that catches anError(and the code that completes such a callback has to catch anErrorin order to pass it, thus violating the recommendation from theErrorclass). Such a callback forces a user to either- Also propagate
Throwablewhich simply delays handling anErrorto a later time and causes more code to run before it is handled, thus increasing the chances of throwing anotherError(again, obvious for anOutOfMemoryError). - Wrap
Errors inExceptions, which is only harmful as it effectively hides the fact that anErroroccurred by making it impossible to detect in any straightforward way. - Handle
Errors, which does not seem to be possible other than by terminating the VM.
- Also propagate