Valentin Kovalenko
Valentin Kovalenko

Reputation: 486

Why does Java expose Error and Java SE API callback methods accept Throwable instead of Exception?

Facts

  1. The Java SE API says about the Error type that it "indicates serious problems that a reasonable application should not try to catch"; also "errors are abnormal conditions that should never occur".
  2. The JLS 11.1.3 "Asynchronous Exceptions" says about VirtualMachineError that 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

  1. Given that an Error represents an abnormal condition that should never occur and that applications should not try to catch it, what are the good reasons to expose the Error type at all in Java SE API instead of handling errors always by terminating the VM without exposing them to applications?
  2. Why do (almost?) all callback methods in the Java SE API, e.g., java.nio.channels.CompletionHandler.failed, CompletionStage.exceptionally, Flow.Subscriber.onError, accept Throwable, which includes Error, instead of accepting Exception? Effectively, a callback that accepts Throwable is not better than code that catches an Error (and the code that completes such a callback has to catch an Error in order to pass it, thus violating the recommendation from the Error class). Such a callback forces a user to either
    • 🤔 Also propagate Throwable which simply delays handling an Error to a later time and causes more code to run before it is handled, thus increasing the chances of throwing another Error (again, obvious for an OutOfMemoryError).
    • 👎 Wrap Errors in Exceptions, which is only harmful as it effectively hides the fact that an Error occurred 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.

Upvotes: 4

Views: 184

Answers (0)

Related Questions