java 捕获 OutOfMemoryError
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5403972/
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
Catching OutOfMemoryError
提问by Viren Pushpanayagam
Is there any point catching an out of memory error (java.lang.OutOfMemoryError
) in Java?
java.lang.OutOfMemoryError
在 Java 中捕获内存不足错误 ( )有什么意义吗?
回答by Epaga
Yes. Here are a few examples where it could make sense:
是的。以下是一些可能有意义的示例:
- if you want to handle it by gracefully closingyour program
- if you want to display the problem to the user or log the error
- depending on your design, you might even be able to clear up memory and restore a working state
- 如果您想通过优雅地关闭程序来处理它
- 如果您想向用户显示问题或记录错误
- 根据您的设计,您甚至可以清除内存并恢复工作状态
However, note that normally (unless you're at a spot where you'll be allocating tons of memory at once), you probably wouldn't specifically catch OutOfMemoryError for these cases, but rather do a catch Throwable
all the way at the top in your main entry point.
但是,请注意,通常情况下(除非您在一次分配大量内存的地方),对于这些情况,您可能不会专门捕获 OutOfMemoryError,而是catch Throwable
一直在顶部执行主要入口点。
回答by Ingo
The golden rule is to only catch errors that you can handle. If you can do something useful after an OutOfMemory error, then go ahead.
黄金法则是只捕获您可以处理的错误。如果您可以在 OutOfMemory 错误后做一些有用的事情,那么继续。
回答by Sean Patrick Floyd
No, catch Exception
and RuntimeException
, but hardly ever (changed from 'never') Error
:
不, catchException
和RuntimeException
,但几乎从来没有(从“从不”改变)Error
:
An Error is a subclass of
Throwable
that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. TheThreadDeath
error, though a "normal" condition, is also a subclass ofError
because most applications should not try to catch it.
Error 是一个子类,
Throwable
它指示合理的应用程序不应尝试捕获的严重问题。大多数此类错误是异常情况。该ThreadDeath
错误虽然是“正常”条件,但也是 的一个子类,Error
因为大多数应用程序不应尝试捕获它。
Note:
I'm quoting the official Javadocs here. If you don't agree, tell Oracle, don't shoot the messenger :-)
注意:
我在这里引用了官方的 Javadoc。如果你不同意,告诉甲骨文,不要射击信使:-)
回答by Stephen C
As some other answers have pointed out, it is a bad ideato catch OutOfMemoryError
and attempt to recover1. Rather than just repeating that the javadoc says you Error
exceptions are not recoverable, I'll try to explain why.
正如其他一些答案所指出的那样,捕获并尝试恢复1是一个坏主意。我将尝试解释原因,而不是重复 javadoc 说您的异常不可恢复。OutOfMemoryError
Error
In fact there are at least two solid reasons why OOME recovery is unwise:
事实上,OOME 恢复不明智的原因至少有两个:
The First Reason is that OOME's are typicallythe result of undiagnosed memory leaks. If your application catches and attempts to recover, the chances are that the leaked memory will still be reachable and hence still won't be reclaimed. So when your application starts doing things it is likely to leak more memory ... and run into another OOME. Sooner or later, the application grinds to a halt.
第一个原因是 OOME通常是未诊断的内存泄漏的结果。如果您的应用程序捕获并尝试恢复,则泄漏的内存可能仍然可以访问,因此仍然不会被回收。因此,当您的应用程序开始执行某些操作时,很可能会泄漏更多内存……并遇到另一个 OOME。应用程序迟早会停止。
Since there is no way you can be absolutely sure that your application doesn't leak, OOME recovery is never going to be a solid, reliable answer.
由于您无法绝对确定您的应用程序不会泄漏,因此 OOME 恢复永远不会成为可靠、可靠的答案。
The Second Reason is that when an OOME occurs, there is a chance that it will do damage to the execution state. It might cause threads to terminate, leaving other threads waiting for notifications that will never arrive, etc. It might occur in the middle of updating a critical application data structure or (possibly worse) a JVM data structure. If your application then attempts to recover, it might lock up, or (worse) it might manage to keep going with corrupted data, and produce unpredictable results.
第二个原因是当 OOME 发生时,它有可能对执行状态造成损害。它可能导致线程终止,让其他线程等待永远不会到达的通知等。它可能发生在更新关键应用程序数据结构或(可能更糟)JVM 数据结构的过程中。如果您的应用程序随后尝试恢复,它可能会锁定,或者(更糟糕的是)它可能设法继续处理损坏的数据,并产生不可预测的结果。
Unless you perform a forensic analysis of your codebase, you can never be entirely sure that this kind of thing won't happen.
除非您对代码库进行取证分析,否则您永远无法完全确定这种事情不会发生。
I won't say you should NEVER attempt to recover from an OOME, but in general it is a risky thing to do. And the more complex your application is, the harder it is to evaluate the risk.
我不会说你永远不要尝试从 OOME 中恢复,但总的来说,这是一件冒险的事情。您的应用程序越复杂,评估风险就越困难。
1 - Here I am talking about catching OOME in an attempt to allow the application to continue running as before; i.e. to recover the application. Catching an OOME in order to perform (or trigger) an orderly shutdown is a different matter.
1 - 我在这里谈论的是捕获 OOME 以试图让应用程序像以前一样继续运行;即恢复应用程序。捕获 OOME 以执行(或触发)有序关闭是另一回事。
回答by Peter Lawrey
If you want to have a graceful shutdown which handles this case specificly.
如果你想要一个优雅的关机来专门处理这种情况。
You can also use it if you may have to allocate a large array and you want to gracefully degrade your system.
如果您可能需要分配一个大数组并且想要优雅地降级您的系统,您也可以使用它。
EDIT: An example of code where I used to check OOM if the stream was corrupted. I have since replace the len check to ensure the len is between 0 and 16 MB instead.
编辑:我用来检查 OOM 是否流已损坏的代码示例。从那以后,我替换了 len 检查以确保 len 介于 0 和 16 MB 之间。
DataInputStream dis = new DataInputStream(socket.getInputStream());
public byte[] readBytes() {
int len = dis.readInt();
try {
byte[] bytes = new byte[len];
dis.readFully(bytes);
return bytes;
} catch(OutOfMemoryError e) {
log.error("Corrupt stream of len="+len);
closeSocket();
return null;
}
}
回答by Andrew Thompson
This has already been mentioned a number of times, but the replies indicate a few people are confused about this (common) recovery technique for an OutOfMemoryError
. Check my post to What if new fails?for a demo of how to do it.
这已经被多次提及,但回复表明有些人对OutOfMemoryError
. 检查我的帖子,如果新的失败怎么办?有关如何操作的演示。
回答by Pushkar
This is one of the errors you should never catch. The reason for this is simple you will not be able to do anything about it at runtime. However if your application is regularly facing this error then you should consider the following strategies to mitigate this issue-
这是您永远不应该发现的错误之一。原因很简单,您将无法在运行时对其进行任何操作。但是,如果您的应用程序经常面临此错误,那么您应该考虑以下策略来缓解此问题-
- Increase the memory available to the JVM by adding jvm args
- 通过添加 jvm args 增加 JVM 可用的内存
-Xms1024m -Xmx1024m
-Xms1024m -Xmx1024m
If the errors still persist then use a profiler like JProfiler or a Eclipse MAT to analyze how much memory your application uses.
Move to a 64 bit system and increase the JVM memory even further.
如果错误仍然存在,则使用 JProfiler 或 Eclipse MAT 之类的分析器来分析您的应用程序使用了多少内存。
移动到 64 位系统并进一步增加 JVM 内存。
回答by Vladimir Ivanov
The only place I have done that was mobile development. You can ask user to close other applications in order to give your application ability to work properly. But that's not the case of Android development.
我唯一做过的地方是移动开发。您可以要求用户关闭其他应用程序,以使您的应用程序能够正常工作。但这不是Android开发的情况。
I don't see any other things you can do with the situation. May be, some appropriate logging or cleanup.
我没有看到你可以对这种情况做任何其他事情。可能是一些适当的日志记录或清理。
回答by developer
It's not an exception; it's an error: java.lang.OutOfMemoryError
这也不例外。这是一个错误:java.lang.OutOfMemoryError
You can catch it as it descends from Throwable:
您可以在它从 Throwable 下降时捕获它:
try {
// create lots of objects here and stash them somewhere
} catch (OutOfMemoryError E) {
// release some (all) of the above objects
}
尝试 {
// 在这里创建很多对象并将它们藏在某个地方
} catch (OutOfMemoryError E) {
// 释放上面的一些(全部)对象
}
However, unless you're doing some rather specific stuff (allocating tons of things within a specific code section, for example) you likely won't be able to catch it as you won't know where it's going to be thrown from.
但是,除非您正在做一些相当具体的事情(例如,在特定的代码部分中分配大量的东西),否则您可能无法捕捉到它,因为您不知道它将从哪里抛出。