Java 异步异常:我能捕获它们吗?

2022-09-02 10:22:27

我一直在阅读JLS,我遇到了11.1.3节。我引用的异步异常

大多数异常是由于发生异常的线程的操作而同步发生的,并且在程序中指定可能导致此类异常的某个点发生。相比之下,异步异常是可能在程序执行过程中的任何时间点发生的异常。

异步异常仅由于以下原因而发生:

[...]

  • Java 虚拟机中的内部错误或资源限制,导致它无法实现 Java 编程语言的语义。在这种情况下,引发的异步异常是 VirtualMachineError 的子类的实例。

是否有可能捕获此类异常以进行日志记录或通知(因为我认为此类内容是不可恢复的)?我怎样才能实现这样的事情?


答案 1

您可以像捕获任何其他异常一样捕获此类异常。唯一的问题是它们可能发生在程序中的任何地方,因此可靠地捕获它们很困难。你基本上必须将所有线程的方法和方法包装在一个块中,但是对于你无法控制的线程(如Swing EDT,或计时器的线程等),你不能这样做。runmaintry..catch

通常不建议捕获 的任何子类,因为 JVM 可能处于不稳定状态,这可能会导致进一步的故障(例如,在 的情况下,您可能没有足够的内存来进行异常处理)。但是,日志记录将是在我眼中捕捉s的有效原因。ErrorOutOfMemoryErrorError

我建议的解决方案是通过将未捕获的异常处理程序设置为默认异常处理程序来为此使用未捕获的异常处理程序。在此处理程序中,如果代码中的任何位置未捕获所有异常和错误,您将获得所有异常和错误,您可以尝试记录它们。


答案 2

捕获这些异常(VirtualMachineError的子类)是没有意义的,因为您没有说明 pogram 所处的状态,文档对虚拟机错误进行了说明:

Java 虚拟机实现会引发一个对象,该对象是 VirtualMethodError 类的子类的实例,当内部错误或资源限制阻止它实现本章中描述的语义时。此规范无法预测在何处可能遇到内部错误或资源限制,也无法准确规定何时可以报告这些错误或资源限制

因此,假设您进入OutOfMemoryError或UnknownError,那么您对此无能为力,一旦您的虚拟信号无法正常工作,您就无法为用户提供任何帮助,因为您的程序也无法正常工作,此外您不知道它发生在什么时间,点和原因,因为它不是由您的程序引起的代码错误。