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