异常 - 何时捕获java.lang.Error?
在什么情况下应该在应用程序上捕获java.lang.Error?
16个解决方案
95 votes
一般来说,从不。但是,有时您需要捕获特定的错误。
如果您正在编写框架代码(加载第三方类),那么捕获LinkageErrors(没有发现类def,不满意的链接,不兼容的类更改)可能是明智的。我还看到一些愚蠢的第三方代码抛出错误的子句,所以你也必须处理它们。
顺便说一下,我不确定从OutOfMemory恢复是不是可能。
Yoni Roit answered 2019-07-06T18:45:18Z
50 votes
决不。 您永远无法确定应用程序是否能够执行下一行代码。 如果您收到OutOfMemoryError,您无法保证能够可靠地执行任何操作。 捕获RuntimeException并检查异常,但绝不会出错。
[http://pmd.sourceforge.net/rules/strictexception.html]
tronda answered 2019-07-06T18:45:49Z
14 votes
在多线程环境中,您最常想要抓住它! 当你抓住它,记录它,并终止整个应用程序! 如果你不这样做,一些可能正在做一些关键部分的线程将会死亡,应用程序的其余部分会认为一切正常。 除此之外,许多不必要的情况都可能发生。一个最小的问题是,如果其他线程由于一个线程不起作用而开始抛出一些异常,那么您将无法轻松找到问题的根。
例如,通常循环应该是:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
即使在某些情况下,您也希望以不同的方式处理不同的错误,例如,在OutOfMemoryError上,您可以定期关闭应用程序(甚至可能释放一些内存,并继续),在其他一些情况下,您可以做的事情并不多。
Sarmun answered 2019-07-06T18:46:29Z
14 votes
通常,您应始终捕获Throwable并将其写入日志或将其显示给用户。 我支持并且每天都看到程序员无法分辨程序中发生了什么。
如果你有一个守护程序线程,那么你必须防止它被终止。 在其他情况下,您的应用程序将正常工作
您应该只捕获最高级别的Throwable。
如果查看错误列表,您会发现大多数错误都可以处理。 例如,Throwable在读取损坏的zip文件时发生。
最常见的错误是Throwable和NoClassDefFoundError,它们在大多数情况下都是运行时问题。
例如:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
可以生成Throwable但它是运行时问题,没有理由终止您的程序。
Throwable主要发生在库不存在或者您使用其他Java版本时。 如果它是您程序的可选部分,那么您不应该终止您的程序。
我可以提供更多示例,说明为什么在顶层捕获Throwable并产生有用的错误消息是个好主意。
Horcrux7 answered 2019-07-06T18:47:42Z
8 votes
非常稀有。
我只是说在一个线程的顶层,以便尝试发出一条消息,其中包含线程死亡的原因。
如果您处于为您执行此类操作的框架中,请将其保留在框架中。
Darron answered 2019-07-06T18:48:20Z
6 votes
几乎从不。 错误旨在成为应用程序通常无法解决的问题。 唯一的例外可能是处理错误的呈现,但即使这可能不会按计划进行,具体取决于错误。
nicerobot answered 2019-07-06T18:48:44Z
6 votes
通常不应该捕获Error,因为它表示应该永远不会发生的异常情况。
从Error类的Java API规范:
Error是Throwable的子类 这表明存在严重的问题 合理的申请不应该尝试 去抓。 大多数此类错误都是 异常情况。[...]
声明不需要方法 它的throws子句的任何子类 在期间可能抛出的错误 执行方法但不是 抓住了,因为这些错误是 不应该的异常情况 发生。
正如规范所提到的那样,Error只会在这种情况下被抛出有可能,当Throwable发生时,应用程序可以做的很少,并且在某些情况下,Java虚拟机本身可能处于不稳定状态(例如Error)
虽然Error是Throwable的子类,这意味着它可以被try-catch子句捕获,但它可能并不是真的需要,因为当JVM抛出Error时,应用程序将处于异常状态。
第11.5节“Java语言规范的例外层次结构”第2版中还有关于此主题的简短部分。
coobird answered 2019-07-06T18:49:47Z
6 votes
如果你疯狂到创建一个新的单元测试框架,你的测试运行器可能需要捕获任何测试用例抛出的java.lang.AssertionError。
否则,请参阅其他答案。
noahlz answered 2019-07-06T18:50:20Z
5 votes
还有一些其他情况,如果你发现错误,你必须重新抛出它。 例如,永远不应该捕获ThreadDeath,如果你在一个包含的环境(如应用服务器)中捕获它,它可能会导致很大的问题:
应用程序只有在必须清理时才应捕获此类的实例 异步终止后。 如果ThreadDeath被方法捕获, 重新抛出它以使线程实际死亡是很重要的。
Guillaume answered 2019-07-06T18:50:52Z
4 votes
很少,很少。
我只为一个非常具体的已知案例做过。例如,如果两个独立的ClassLoader加载相同的DLL,则可能抛出java.lang.UnsatisfiedLinkError。 (我同意我应该将JAR移动到共享的类加载器)
但最常见的情况是您需要登录才能知道用户投诉时发生了什么。 您希望向用户发送消息或弹出窗口,而不是默默地死亡。
即使是C / C ++中的程序员,他们也会弹出错误并告诉人们在退出之前不理解的东西(例如内存故障)。
Dennis C answered 2019-07-06T18:51:39Z
3 votes
在Android应用程序中,我正在捕获java.lang.VerifyError。 我正在使用的库不能在具有旧版操作系统的设备中工作,库代码会抛出这样的错误。 我当然可以通过在运行时检查OS的版本来避免错误,但是:
支持最旧的SDK可能会在将来针对特定库进行更改
try-catch错误块是更大的回退机制的一部分。 一些特定的设备,虽然它们应该支持该库,但会抛出异常。 我捕获VerifyError和所有异常以使用后备解决方案。
kgiannakakis answered 2019-07-06T18:52:19Z
3 votes
在测试环境中捕获java.lang.AssertionError非常方便...
Jono answered 2019-07-06T18:52:44Z
2 votes
理想情况下,我们不应该处理/捕获错误。 但根据框架或应用程序的要求,可能存在我们需要做的情况。 假设我有一个XML Parser守护程序,它实现了DOM Parser,它消耗更多内存。 如果有一个像Parser线程这样的要求在它出现OutOfMemoryError时不应该死掉,而是它应该处理它并向应用程序/框架的管理员发送消息/邮件。
user3510364 answered 2019-07-06T18:53:11Z
1 votes
理想情况下,我们永远不应该在Java应用程序中捕获Error,因为它是一种异常情况。 应用程序将处于异常状态,可能导致运行或出现严重错误的结果。
Vivek answered 2019-07-06T18:53:36Z
1 votes
在检查断言的单元测试中捕获错误可能是适当的。 如果有人禁用断言或以其他方式删除您想要知道的断言
Chanoch answered 2019-07-06T18:54:02Z
1 votes
当JVM不再按预期工作或接近时,会出现错误。 如果你发现错误,就不能保证catch块会运行,甚至不会保证它会一直运行到最后。
它还将取决于正在运行的计算机,当前的内存状态,因此无法测试,尝试并尽力而为。 你只会得到一个有害的结果。
您还将降低代码的可读性。
Nicolas Zozol answered 2019-07-06T18:54:41Z