为什么Java expose Error和Java SE API回调方法接受Throwable而不是Exception? 事实 JavaSEAPI说明了它所使用的错误类型;还有 JLS 11.1.3“异步异常”说明它是一个虚拟机错误 解读

为什么Java expose Error和Java SE API回调方法接受Throwable而不是Exception? 事实 JavaSEAPI说明了它所使用的错误类型;还有 JLS 11.1.3“异步异常”说明它是一个虚拟机错误 解读,java,exception,callback,throwable,Java,Exception,Callback,Throwable,规范不仅明确建议不要捕获错误s,而且还指出,如果发生VirtualMachineError,则无法保证语言语义的正确性。看来Thread.stop/ThreadDeath也至少可以应用于任何虚拟机错误。由于允许,对于LinkageError,情况也是如此:没有任何代码需要它或防范它,因此当它发生时,可能会导致损坏对象的状态,就像ThreadDeath或VirtualMachineError一样 (在我看来)上述情况足以决定没有可靠的方法来处理错误。我看到的唯一出路是使用一个调用系统的线程.Unc

规范不仅明确建议不要捕获
错误
s,而且还指出,如果发生
VirtualMachineError
,则无法保证语言语义的正确性。看来
Thread.stop
/
ThreadDeath
也至少可以应用于任何
虚拟机错误
。由于允许,对于
LinkageError
,情况也是如此:没有任何代码需要它或防范它,因此当它发生时,可能会导致损坏对象的状态,就像
ThreadDeath
VirtualMachineError
一样

(在我看来)上述情况足以决定没有可靠的方法来处理
错误。我看到的唯一出路是使用一个调用
系统的
线程.UncaughtExceptionHandler
,退出运行时.halt
,并在终止VM之前尝试记录
错误(日志记录尝试可能会失败,并导致另一个由原始
错误引起的
错误,如果原始
错误
OutOfMemoryError
,这一点尤其明显)

问题
  • 考虑到
    错误
    代表了一种不应该发生的异常情况,并且应用程序不应该试图捕获它,那么在Java SE API中公开
    错误
    类型而不是总是通过终止VM而不向应用程序公开错误来处理错误的好理由是什么
  • 为什么(几乎?)Java SE API中的所有回调方法(例如,接受<代码>Throwable
  • ,其中包括<代码>错误
    ),而不是接受<代码>异常
    ?实际上,接受<代码>Throwable
    的回调并不比捕获<代码>错误的回调好(完成这种回调的代码必须捕获
    错误
    ,才能传递它,从而违反
    错误
    类的建议)

    • 我可以考虑一些边缘情况——如果您的程序应该加载一些外部类文件(可能由用户生成),然后调用这些类中的一些方法。如果类文件编写不正确,这些方法可能不存在,并且会发生
      NoSuchMethodError
      。您希望虚拟机崩溃吗?还是希望显示错误消息?Java SE JRE执行“唯一有害”操作#2b始终通过将
      NoClassDefFoundError
      包装在
      ClassNotFoundException
      中,这完全是由运行时类路径扫描程序例行处理的。@Sweeper
      NoSuchMethodError
      的文档说明,如果应用程序试图调用类(静态或实例)的指定方法,它将被抛出因此,是的,如果我有调用
      MyClass.method()
      的代码,而这个调用突然导致
      NoSuchMethodError
      ,终止它看起来确实合理。
      Error
      声称它不应该被捕获,也就是说,它不应该是可恢复的(如果存在安全可恢复的
      错误
      ,那么它应该是一个
      异常
      )。如果不可恢复,那么为什么要公开它?@chrylis小心光学-“在
      ClassNotFoundException
      中包装
      NoClassDefFoundError
      ”-我不确定是否是这种情况。您能告诉我在哪里可以找到指定的或看到JDK暴露
      NoClassDefFoundError
      的一些证据作为(即,将其包装)的原因吗
      ClassNotFoundException
      ?@chrylis小心光学-一个简单的例子,Java SE API在
      Exception
      s中指定包装
      Error
      s是
      FutureTask.setException
      方法,它导致提供的
      Throwable
      被包装在
      ExecutionException
      中。这样的API设计使得只有当
      Error
      s被认为是预期的和可恢复的时,它才有意义。但这种考虑与
      Error
      类型在其文档中表达的理念相矛盾