何时赶上java.lang.Error?

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

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

如果你正在编写framework-ish代码(加载第三方类),那么捕获链接错误(没有find类的def,不满意的链接,不兼容的类更改)可能是明智的。 我也看到一些愚蠢的第三方代码抛出错误sublcasses,所以你将不得不处理这些。

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

决不。 你永远不能确定应用程序是否能够执行下一行代码。 如果您遇到OutOfMemoryError ,则不能保证您能够可靠地执行任何操作 。 Catch RuntimeException和检查exception,但从来没有错误。

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

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

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

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

如果你看看错误列表,你会发现大部分都可以被处理。 例如,读取损坏的zip文件时发生ZipError

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

例如:

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

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

NoClassDefFoundError主要发生在库不存在的情况下,或者您使用另一个Java版本时。 如果它是你的程序的一个可选部分,那么你不应该终止你的程序。

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

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

例如,通常循环应该是:

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

即使在某些情况下,您也可能想要以不同的方式处理不同的错误,例如,在OutOfMemoryError上,您可以定期closures应用程序(甚至可能释放一些内存,然后继续),而在其他一些情况下,则可以做的事情不多。

非常稀有。

我只会说,在一个线程的顶级水平,以尝试发出一个线程死亡的原因的消息。

如果你在一个为你做这种事情的框架中,把它留给框架。

几乎从不。 错误被devise成应用程序通常不能做任何事情的问题。 唯一的例外可能是处理错误的表示,但即使这样也可能不会按计划进行,这取决于错误。

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

Error类的Java API规范:

一个ErrorThrowable一个子类,表示一个合理的应用程序不应该试图捕捉的严重问题。 大多数这样的错误是exception的条件 […]

一个方法不需要在throws子句中声明在执行该方法期间可能抛出的错误的任何子类,但是没有被捕获,因为这些错误是不应该发生的exception情况。

正如规范所提到的,只有在机会是Error发生时才会抛出Error ,应用程序可以做的很less,在某些情况下,Java虚拟机本身可能处于不稳定状态(如VirtualMachineError

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

在第11.5节“ Java语言规范 的例外层次结构 ” (第2版)中也有关于此主题的简短部分。

如果你疯狂地创build一个新的unit testing框架,你的testing运行器可能需要捕获任何testing用例抛出的java.lang.AssertionError。

否则,请参阅其他答案。

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

只有在asynchronous终止后,应用程序才能捕获此类的实例。 如果ThreadDeath被一个方法捕获,重新抛出它是非常重要的,这样线程就会死亡。

非常,很less。

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

但最常见的情况是,您需要login才能知道用户来抱怨时发生了什么。 你想给用户一个消息或popup窗口,而不是默默地死去。

即使是C / C ++的程序员,他们也会popup一个错误信息,告诉用户在退出之前不理解的内容(例如内存失败)。

在Android应用程序中,我正在捕获一个java.lang.VerifyError 。 我正在使用的库不适用于具有旧版本操作系统的设备,并且库代码会抛出这样的错误。 我当然可以通过在运行时检查OS的版本来避免错误,但是:

  • 对于特定的库,未来最老的SDK可能会更改
  • try-catch错误块是更大的回退机制的一部分。 一些特定的设备,虽然他们应该支持图书馆,抛出exception。 我捕获VerifyError和所有exception使用回退解决scheme。

在testing环境中捕获java.lang.AssertionError非常方便…

理想情况下,我们不应该处理/发现错误。 但是根据框架或应用的要求,可能有些情况需要我们去做。 说我有一个XMLparsing器守护进程,它实现DOMparsing器 ,消耗更多的内存。 如果有像Parser线程这样的需求,在得到OutOfMemoryError的时候不应该死掉,而是应该处理它,并发送一个消息/邮件给应用程序/框架的pipe理员。

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

在unit testing中发现检查断言的错误可能是合适的。 如果有人禁用了断言或者删除了你想知道的断言

当JVM没有像预期的那样工作,或者处于边缘时,会出现错误。 如果发现错误,则不能保证catch块将运行,甚至更less的运行直到结束。

它也将取决于正在运行的计算机,当前的内存状态,所以没有办法testing,尽力而为。 你只会有一个糟糕的结果。

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