什么时候捕获 java.lang.Error?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/352780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to catch java.lang.Error?
提问by Jo?o
In what situations should one catch java.lang.Error
on an application?
在什么情况下应该抓住java.lang.Error
应用程序?
采纳答案by Yoni Roit
Generally, never.
一般来说,从不。
However, sometimes you need to catch specific errors.
但是,有时您需要捕获特定错误。
If you're writing framework-ish code (loading 3rd party classes), it might be wise to catch LinkageError
(no class def found, unsatisfied link, incompatible class change).
如果您正在编写框架式代码(加载第 3 方类),那么捕获LinkageError
(未找到类定义、不满意的链接、不兼容的类更改)可能是明智的。
I've also seen some stupid 3rd-party code throwing subclasses of Error
, so you'll have to handle those as well.
我还看到一些愚蠢的 3rd-party 代码抛出 的子类Error
,所以你也必须处理这些。
By the way, I'm not sure it isn't possible to recover from OutOfMemoryError
.
顺便说一句,我不确定是否不可能从OutOfMemoryError
.
回答by nicerobot
Almost never. Errors are designed to be issues that applications generally can't do anything about. The only exception might be to handle the presentation of the error but even that might not go as planned depending on the error.
几乎从不。错误被设计为应用程序通常无法解决的问题。唯一的例外可能是处理错误的呈现,但根据错误的不同,即使那样也可能不会按计划进行。
回答by tronda
Never. You can never be sure that the application is able to execute the next line of code. If you get an OutOfMemoryError
, you have no guarantee that you will be able to do anything reliably. Catch RuntimeException and checked Exceptions, but never Errors.
绝不。您永远无法确定应用程序是否能够执行下一行代码。如果您获得OutOfMemoryError
,则无法保证您将能够可靠地执行任何操作。捕获 RuntimeException 和已检查的异常,但从不捕获错误。
回答by Guillaume
And there are a couple of other cases where if you catch an Error, you have to rethrow it. For example ThreadDeathshould never be caught, it can cause big problem is you catch it in a contained environment (eg. an application server) :
还有一些其他情况,如果你发现一个错误,你必须重新抛出它。例如ThreadDeath永远不应该被捕获,它可能会导致大问题,因为您在包含的环境(例如应用程序服务器)中捕获它:
An application should catch instances of this class only if it must clean up after being terminated asynchronously. If ThreadDeath is caught by a method, it is important that it be rethrown so that the thread actually dies.
仅当应用程序在异步终止后必须进行清理时,它才应捕获此类的实例。如果 ThreadDeath 被方法捕获,重要的是将其重新抛出,以便线程实际死亡。
回答by Darron
Very rarely.
非常稀有。
I'd say only at the top level of a thread in order to ATTEMPT to issue a message with the reason for a thread dying.
我只会在线程的顶层说,以便尝试发出一条消息,原因是线程死亡。
If you are in a framework that does this sort of thing for you, leave it to the framework.
如果你在一个为你做这种事情的框架中,把它留给框架。
回答by coobird
An Error
usually shouldn't be caught, as it indicates an abnormal condition that should never occur.
一个Error
通常不应该被捕获,因为它表明绝不应该出现的异常情况。
From the Java API Specification for the Error
class:
来自Error
该类的 Java API 规范:
An
Error
is a subclass ofThrowable
that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. [...]A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
An
Error
是一个子类Throwable
,表示合理的应用程序不应尝试捕获的严重问题。大多数此类错误是异常情况。[...]一个方法不需要在它的 throws 子句中声明在方法执行期间可能抛出但没有被捕获的 Error 的任何子类,因为这些错误是不应该发生的异常情况。
As the specification mentions, an Error
is only thrown in circumstances that are
Chances are, when an Error
occurs, there is very little the application can do, and in some circumstances, the Java Virtual Machine itself may be in an unstable state (such as VirtualMachineError
)
由于规范中提到,一个Error
只抛出是有机会,当情况Error
发生时,很少有应用程序可以做的,在某些情况下,Java虚拟机本身可能处于不稳定的状态(如VirtualMachineError
)
Although an Error
is a subclass of Throwable
which means that it can be caught by a try-catch
clause, but it probably isn't really needed, as the application will be in an abnormal state when an Error
is thrown by the JVM.
虽然 anError
是其子类,Throwable
这意味着它可以被try-catch
子句捕获,但它可能并不是真正需要的,因为当Error
JVM 抛出an 时,应用程序将处于异常状态。
There's also a short section on this topic in Section 11.5 The Exception Hierarchyof the Java Language Specification, 2nd Edition.
第11.5节The Exception Hierarchyof the Java Language Specification, 2nd Edition 中还有一个关于此主题的简短部分。
回答by Dennis C
Very, very rarely.
很少,很少。
I did it only for one very very specific known cases. For example, java.lang.UnsatisfiedLinkError could be throw if two independence ClassLoaderload same DLL. (I agree that I should move the JAR to a shared classloader)
我只针对一个非常非常具体的已知案例这样做。例如,如果两个独立的 ClassLoader加载相同的 DLL ,则可能抛出 java.lang.UnsatisfiedLinkError 。(我同意我应该将 JAR 移动到共享类加载器)
But most common case is that you needed logging in order to know what happened when user come to complain. You want a message or a popup to user, rather then silently dead.
但最常见的情况是您需要登录才能知道用户投诉时发生了什么。你想要一条消息或一个弹出窗口给用户,而不是默默地死。
Even programmer in C/C++, they pop an error and tell something people don't understand before it exit (e.g. memory failure).
即使是 C/C++ 程序员,他们也会弹出一个错误并在它退出之前告诉人们不理解的东西(例如内存故障)。
回答by noahlz
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.AssertionError。
Otherwise, see other answers.
否则,请参阅其他答案。
回答by Horcrux7
Generally you should always catch java.lang.Error
and write it to a log or display it to the user. I work in support and see daily that programmers cannot tell what has happened in a program.
通常,您应该始终捕获java.lang.Error
并将其写入日志或将其显示给用户。我在支持部门工作,每天都看到程序员无法判断程序中发生了什么。
If you have a daemon thread then you must prevent it being terminated. In other cases your application will work correctly.
如果您有一个守护线程,那么您必须防止它被终止。在其他情况下,您的应用程序将正常工作。
You should only catch java.lang.Error
at the highest level.
你应该只java.lang.Error
在最高级别接球。
If you look at the list of errors you will see that most can be handled. For example a ZipError
occurs on reading corrupt zip files.
如果您查看错误列表,您会发现大多数都可以处理。例如ZipError
,在读取损坏的 zip 文件时发生。
The most common errors are OutOfMemoryError
and NoClassDefFoundError
, which are both in most cases runtime problems.
最常见的错误是OutOfMemoryError
和NoClassDefFoundError
,这在大多数情况下都是运行时问题。
For example:
例如:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
can produce an OutOfMemoryError
but it is a runtime problem and no reason to terminate your program.
可以产生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.
NoClassDefFoundError
如果库不存在或者您使用另一个 Java 版本,通常会发生这种情况。如果它是您程序的可选部分,那么您不应终止您的程序。
I can give many more examples of why it is a good idea to catch Throwable
at the top level and produce a helpful error message.
我可以举出更多的例子来说明为什么Throwable
在顶层捕获并生成有用的错误消息是个好主意。
回答by Sarmun
In multithreaded environment, you most often want to catch it! When you catch it, log it, and terminate whole application! If you don't do that, some thread that might be doing some crucial part would be dead, and rest of the application will think that everything is normal. Out of that, many unwanted situations can happen. One smallest problem is that you wouldn't be able to easily find root of the problem, if other threads start throwing some exceptions because of one thread not working.
在多线程环境中,你最常想抓住它!当您捕获它时,记录它并终止整个应用程序!如果你不这样做,一些可能正在做一些关键部分的线程就会死掉,而应用程序的其余部分会认为一切正常。除此之外,可能会发生许多不需要的情况。一个最小的问题是,如果其他线程由于一个线程不工作而开始抛出一些异常,您将无法轻松找到问题的根源。
For example, usually loop should be:
例如,通常循环应该是:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Even in some cases, you would want to handle different Errors differently, for example, on OutOfMemoryError you would be able to close application regularly (even maybe free some memory, and continue), on some others, there is not much you can do.
即使在某些情况下,您可能希望以不同的方式处理不同的错误,例如,在 OutOfMemoryError 上,您将能够定期关闭应用程序(甚至可能释放一些内存,然后继续),在其他一些情况下,您无能为力。