为什么 Java 公开 Error 和 Java SE API 回调方法接受 Throwable 而不是 Exception?

问题描述

事实

  1. Java SE API 说明了它 "indicates serious problems that a reasonable application should not try to catch"Error 类型;还有"errors are abnormal conditions that should never occur"
  2. JLS 11.1.3“异步异常”说明 VirtualMachineError一个 "internal error or resource limitation in the Java Virtual Machine that prevents it from implementing the semantics of the Java programming language"

解释

规范不仅明确建议不要捕获 Error,而且还说如果 VirtualMachineError 发生,则无法保证语言语义成立。看来,arguments against Thread.stop/ThreadDeath 至少也可以应用于任何 VirtualMachineError。由于 lazy resolution 被允许,LinkageError 也是如此:没有代码期望它或防范它,因此当它发生时,它可能会导致破坏对象的状态,就像 {{1} }} 或 ThreadDeath

以上似乎(对我而言)足以决定没有可靠的方法来处理 VirtualMachineError。我看到的唯一出路是有一个 Error 调用 Thread.UncaughtExceptionHandler/System.exit 并且可能尝试在终止 VM 之前记录 Runtime.halt(记录尝试可能只是失败另一个 Error 由原始 Error 引起,如果原始 ErrorOutOfMemoryError,这一点尤其明显)。

问题

  1. 鉴于 Error 表示不应该发生的异常情况并且应用程序不应尝试捕获它,那么在 Java SE API 中完全公开 Error 类型的充分理由是什么?总是通过终止虚拟机而不将它们暴露给应用程序来处理错误
  2. 为什么(几乎?)Java SE API 中的所有回调方法,例如java.nio.channels.CompletionHandler.failedCompletionStage.exceptionallyFlow.Subscriber.onError,都接受Throwable,其中包括{{1 }},而不是接受Error?实际上,接受 Exception 的回调并不比捕获 Throwable代码更好(完成此类回调的代码必须捕获 Error 才能传递它,从而违反了Error 类的推荐)。这样的回调迫使用户要么
    • ? 还传播 Error,它只是将处理 Throwable 延迟到以后,并导致更多代码在处理之前运行,从而增加抛出另一个 Error 的机会(再次,对于 Error 很明显)。
    • ? 将 OutOfMemoryError 包裹在 Error 中,这只是有害的,因为它有效地隐藏了 Exception 发生的事实,使其无法以任何直接的方式检测。立>
    • ? 处理 Error,这似乎除了终止 VM 之外是不可能的。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)