关于Java.lang.Error的问题

3

有很多关于java.lang.Error的帖子说它不应该被捕获。我的问题是,如果不应该捕获它,那么它的用途是什么?既然它是Throwable,我们可以在try catch中捕获它。我读过一些帖子,比如只有在某些情况下才应该捕获它,如何知道这些情况。

简而言之,我想知道在捕获Error时会出现什么问题。它背后的处理过程是什么?为什么他们要制作Error及其子类?如果我的应用程序不能捕获它们,那么是谁捕获它们?为什么我的代码无法处理这个已经捕获的Error?如果我只是捕获一个Error并在Catch块中编写一些处理代码,那么那段代码会运行吗?

3个回答

1

错误(特别是VirtualMachineError的子类)表示JVM遇到了内部问题 - 这意味着其内部状态可能不再一致。如果您捕获错误并尝试恢复,则未来的行为是未定义的。错误可抛出,这样它们就可以被抛出 - 例如,您可以自己处理本机库中无法恢复的错误(例如,该库可能已写入JVM内存或破坏了其内部静态状态)。在所有可抛出的情况下都使用相同的堆栈跟踪和堆栈跟踪生成机制 - 使用另一种机制执行相同操作是愚蠢的。

JVM中大多数不是VirtualMachineErrors的错误是本机库可能会破坏其静态状态的情况 - 例如AWTError、ZipError。

但是,在某些罕见情况下,捕获错误是明智的:在测试框架中的AssertionError以及需要处理运行时不同版本库的存在/不存在的LinkageError。这是一个非常罕见的要求,最好通过反射来处理。


1

所有规则都有例外(除了这条)。

即使每个人都说你不应该这样做,在许多情况下捕获java.lang.Error是完全适当的。规则的逻辑是:“在检测到致命条件后,不要尝试继续运行应用程序”。因此,在抛出此类错误后进行操作之前必须小心。系统可能无法在此后继续执行任务。

对于一个 servlet 捕获 OutOfMemoryError、记录错误并销毁会话可能是可以接受的。也许问题就出在那个准确的会话上。销毁它可以恢复内存并允许其他用户继续使用系统。但是,您应该有一种机制来实时跟踪这些错误,以便于:

  1. 修复编程错误 (AssertionError,StackOverflowError)
  2. 修复配置错误 (UnsatisfiedLinkError)
  3. 更正JVM大小参数 (OutOfMemoryError)

这种处理应该在调用堆栈中非常“高”的位置完成(即在 main() 附近进行主循环(或等效))。我认为在深层代码中捕获 Error 不是一个好的做法,这些情况下至少应该重新抛出错误。


0

类似的问题已经在这里得到了回答 - 何时捕获java.lang.Error?

基本上,您不应该尝试捕获它,因为它会在一些严重的问题发生时抛出,比如当您的线程由于某种原因死亡并且无法恢复时。然而,在处理框架本身时有时需要捕获错误,如上面的URL所述。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接