何时捕获 java.lang。错误?

在什么情况下应该在应用程序上捕获 java.lang.Error

157986 次浏览

几乎没有。错误被设计成应用程序通常无法处理的问题。唯一的例外可能是处理错误的表示,但即使这样也可能不会按计划进行,这取决于错误。

从来没有。您永远不能确定应用程序是否能够执行下一行代码。如果你得到一个 OutOfMemoryError,你就得到了 不能保证你能做任何可靠的事情。捕获 RuntimeException 并选中 Exception,但绝不捕获错误。

Http://pmd.sourceforge.net/rules/strictexception.html

还有一些其他情况下,如果你捕捉到一个错误,你 必须重新抛出。例如,死亡之线永远不应该被捕获,如果在一个包含的环境(比如应用程序服务器)中捕获它,可能会导致大问题:

应用程序只有在必须清理时才应捕获此类的实例 如果 ThreadDeath 被一个方法捕获, 重新抛出它很重要,这样线程实际上就死了。

一般来说,从来没有。

但是,有时您需要捕获特定的错误。

如果您正在编写类似框架的代码(加载第三方类) ,那么最好捕捉 LinkageError(没有找到类定义,没有满意的链接,不兼容的类更改)。

我还看到一些愚蠢的第三方代码抛出 Error的子类,因此您也必须处理这些代码。

顺便说一下,我不确定是否有可能从 OutOfMemoryError恢复。

很少。

我会说,只有在线程的顶层,才能通过 ATTEMPT 发出消息,说明线程死亡的原因。

If you are in a framework that does this sort of thing for you, leave it to the framework.

Error通常不应该被捕获,因为它是 表示不应该发生的异常情况

来自 Error类的 JavaAPI 规范:

ErrorThrowable的一个子类 表明严重的问题 reasonable application should not try 大多数这样的错误是 异常情况

中声明的方法不是必需的 它的抛出子句的任何子类 过程中可能引发的错误 方法的执行,但不执行 因为这些错误是 不应该出现的异常情况 发生。

正如规范所提到的,Error仅在以下情况下抛出 当出现 Error时,应用程序可以做的很少,在某些情况下,Java 虚拟机本身可能处于不稳定状态(比如 VirtualMachineError)

尽管 ErrorThrowable的一个子类,这意味着它可以被 try-catch子句捕获,但是它可能并不是真正需要的,因为当 JVM 抛出 Error时,应用程序将处于异常状态。

There's also a short section on this topic in Section 11.5异常层次结构 of the Java 语言规范,第2版.

非常,非常罕见。

我这么做只是为了一个非常特殊的已知案例。 比如 java.lang。如果两个 independence ClassLoader加载相同的 DLL,则可能抛出不满意的 LinkError。(我同意我应该将 JAR 移动到一个共享类加载器)

但是最常见的情况是,您需要通过日志记录来了解当用户来投诉时发生了什么。你想要一个消息或弹出窗口给用户,而不是静静地死去。

即使是 C/C + + 的程序员,他们也会弹出一个错误,在它退出之前告诉人们一些人们不理解的东西(例如内存故障)。

If you are crazy enough to be creating a new unit test framework, your test runner will probably need to catch java.lang.AssertionError thrown by any test cases.

否则,看看其他答案。

一般来说,应该总是捕获 java.lang.Error并将其写入日志或显示给用户。我从事支持工作,每天都看到程序员不能说出程序中发生了什么。

如果您有一个守护进程线程,那么您必须防止它被终止。在其他情况下,应用程序将正常工作。

您应该只能在最高级别捕获 java.lang.Error

如果您查看错误列表,您将看到大多数错误都可以处理。例如,在读取损坏的 zip 文件时发生 ZipError

最常见的错误是 OutOfMemoryErrorNoClassDefFoundError,它们在大多数情况下都是运行时问题。

例如:

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

可以产生 OutOfMemoryError,但这是一个运行时问题,没有理由终止您的程序。

NoClassDefFoundError occur mostly if a library is not present or if you work with another Java version. If it is an optional part of your program then you should not terminate your program.

我可以给出更多的例子来说明为什么在顶层捕获 Throwable并产生有用的错误消息是一个好主意。

在多线程环境中,您最经常想要捕捉它!当您捕捉到它时,记录它,并终止整个应用程序!如果不这样做,可能正在执行某些关键部分的某些线程就会死亡,应用程序的其余部分将认为一切正常。由此,许多不必要的情况可能会发生。 一个最小的问题是,如果其他线程因为一个线程不工作而开始抛出一些异常,那么您将无法轻松地找到问题的根源。

例如,通常循环应该是:

try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}

即使在某些情况下,你也会希望以不同的方式处理不同的错误,例如,在 OutOfMemory 错误上,你可以定期关闭应用程序(甚至可能释放一些内存,然后继续) ,在另一些情况下,你能做的不多。

理想情况下,我们不应该在 Java 应用程序中捕获 Error,因为它是一种异常情况。应用程序将处于异常状态,并可能导致卡车或给出一些严重错误的结果。

在检查断言执行情况的单元测试中捕获错误可能是合适的。如果有人禁用断言或以其他方式删除您想要知道的断言

在一个 Android 应用程序中,我正在捕捉一个 Lang. VerifyError。我正在使用的库不能在使用旧版本操作系统的设备上工作,库代码会抛出这样的错误。当然,我可以通过在运行时检查操作系统的版本来避免这个错误,但是:

  • 最早支持的 SDK 将来可能会因为特定的库而发生变化
  • Try-catch 错误块是更大的后退机制的一部分。一些特定的设备,尽管它们应该支持库,却抛出异常。我捕获 VerifyError 和所有异常以使用备用解决方案。

当 JVM 不再像预期的那样工作,或即将工作时,会出现一个错误。如果您捕捉到一个错误,不能保证 catch 块会运行,更不能保证它会一直运行到结束。

它还将取决于运行中的计算机,当前的内存状态,所以没有办法来测试,尽力而为。你只会有一个危险的结果。

您还将降低代码的可读性。

在测试环境中捕获 java.lang.AssertionError 非常方便..。

理想情况下,我们不应该处理/捕获错误。但是,在某些情况下,我们可能需要根据框架或应用程序的需求进行操作。假设我有一个 XML 解析器守护进程,它实现了消耗更多内存的 DOM Parser。如果有像解析器线程这样的需求,当它获得 OutOfMemoryError时不应该死亡,相反,它应该处理它并向应用程序/框架的管理员发送消息/邮件。