何时捕获java.lang.Error?

时间:2008-12-09 13:56:02

标签: java exception error-handling exception-handling

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

16 个答案:

答案 0 :(得分:96)

一般来说,永远不会。 但是,有时您需要捕获特定的错误。

如果你正在编写框架代码(加载第三方类),那么捕获LinkageErrors(没有发现类def,不满意的链接,不兼容的类更改)可能是明智的。 我也看到一些愚蠢的第三方代码抛出错误的子句,所以你必须处理这些。

顺便说一句,我不确定是否无法从OutOfMemory中恢复。

答案 1 :(得分:50)

从不。您永远无法确定应用程序是否能够执行下一行代码。如果您获得OutOfMemoryError,则可以no guarantee that you will be able to do anything reliably。 Catch RuntimeException和checked Exceptions,但从不出错。

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

答案 2 :(得分:15)

通常,您应始终捕获java.lang.Error并将其写入日志或将其显示给用户。我支持并且每天看到程序员无法分辨程序中发生了什么。

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

你应该只抓住最高级别的java.lang.Error

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

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

例如:

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

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

如果库不存在或者您使用其他Java版本,

NoClassDefFoundError主要发生。如果它是您程序的可选部分,那么您不应该终止您的程序。

我可以提供更多示例,说明为什么在顶层捕获Throwable并产生有用的错误消息是个好主意。

答案 3 :(得分:14)

在多线程环境中,您最常想要抓住它!当你抓住它,记录它,并终止整个应用程序!如果你不这样做,一些可能正在做一些关键部分的线程将会死亡,应用程序的其余部分会认为一切正常。除此之外,许多不必要的情况都可能发生。 一个最小的问题是,如果其他线程由于一个线程不起作用而开始抛出一些异常,你将无法轻易找到问题的根。

例如,通常循环应该是:

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

即使在某些情况下,您也希望以不同的方式处理不同的错误,例如,在OutOfMemoryError上,您可以定期关闭应用程序(甚至可以释放一些内存,并继续),在其他一些情况下,您的数据并不多能做到。

答案 4 :(得分:8)

很少。

我只是说在一个线程的顶级,以便ATTEMPT发出一条消息,说明线程死亡的原因。

如果您处于为您做这类事情的框架中,请将其留在框架中。

答案 5 :(得分:6)

几乎没有。错误旨在成为应用程序通常无法执行任何操作的问题。唯一的例外可能是处理错误的呈现,但即使这可能不会按计划进行,具体取决于错误。

答案 6 :(得分:6)

通常不应该抓住Error ,因为表示不应该发生的异常情况

来自Error类的Java API规范:

  

ErrorThrowable的子类   这表明存在严重的问题   合理的申请不应该尝试   去抓。大多数此类错误都是   异常情况。 [...]

     

声明输入不需要方法   它的throws子句的任何子类   在期间可能抛出的错误   执行方法但不是   抓住了,因为这些错误是   不应该的异常情况   发生。

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

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

11.5 The Exception HierarchyJava Language Specification, 2nd Edition部分还有关于此主题的简短部分。

答案 7 :(得分:6)

如果你疯狂到创建一个新的单元测试框架,你的测试运行器可能需要捕获任何测试用例抛出的java.lang.AssertionError。

否则,请参阅其他答案。

答案 8 :(得分:5)

还有一些其他情况,如果你发现错误, 必须重新抛出 。例如,永远不应该捕获ThreadDeath,如果你在一个包含的环境(如应用服务器)中捕获它会导致很大的问题:

  

只有在必须清理的情况下,应用程序才应捕获此类的实例   异步终止后。如果ThreadDeath被方法捕获,   重新抛出它以使线程实际死亡是很重要的。

答案 9 :(得分:4)

很少,很少。

我只为一个非常具体的已知病例做过。 例如,如果两个独立ClassLoader 加载相同的DLL,则可能抛出java.lang.UnsatisfiedLinkError。 (我同意我应该将JAR移动到共享的类加载器)

但最常见的情况是您需要登录才能知道用户投诉时发生了什么。你想要一条消息或弹出窗口给用户,而不是默默地死去。

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

答案 10 :(得分:3)

在Android应用程序中,我正在捕捉java.lang.VerifyError。我正在使用的库将无法在具有旧版本操作系统的设备中工作,并且库代码将引发此类错误。我当然可以通过在运行时检查操作系统的版本来避免错误,但是:

  • 支持最旧的SDK可能会在将来针对特定库进行更改
  • try-catch错误块是更大的后退机制的一部分。一些特定的设备,虽然它们应该支持该库,但会抛出异常。我捕获VerifyError和所有异常以使用后备解决方案。

答案 11 :(得分:3)

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

答案 12 :(得分:2)

理想情况下,我们不应该处理/捕获错误。但根据框架或应用程序的要求,可能存在我们需要做的情况。假设我有一个XML Parser守护程序,它实现了 DOM Parser ,它消耗更多的内存。如果有一个类似Parser线程的要求,当它变为 OutOfMemoryError 时不应该死亡,而是它应该处理它并向应用程序/框架的管理员发送消息/邮件。

答案 13 :(得分:1)

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

答案 14 :(得分:1)

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

答案 15 :(得分:1)

当JVM不再按预期工作或接近时,会出现错误。如果你发现错误,就不能保证catch块会运行,甚至不会保证它会一直运行到最后。

它还将取决于正在运行的计算机,当前的内存状态,因此无法测试,尝试并尽力而为。你只会有一个不幸的结果。

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