Java 捕捉出内存错误
在java中捕获内存不足错误(Java 捕捉出内存错误,java,out-of-memory,Java,Out Of Memory,在java中捕获内存不足错误(java.lang.OutOfMemoryError)有什么意义吗?是。以下是一些有意义的例子: 如果您想通过优雅地关闭程序来处理它 如果要向用户显示问题或记录错误 根据您的设计,您甚至可以清除内存并恢复工作状态 但是,请注意,通常情况下(除非您处于一次分配大量内存的位置),对于这些情况,您可能不会专门捕获OutOfMemoryError,而是在主入口点的顶部执行一个捕获丢弃的。不,捕获异常和运行时异常,但几乎从未(从“从未”改为): 错误是Throwable
java.lang.OutOfMemoryError
)有什么意义吗?是。以下是一些有意义的例子:
- 如果您想通过优雅地关闭程序来处理它
- 如果要向用户显示问题或记录错误
- 根据您的设计,您甚至可以清除内存并恢复工作状态
但是,请注意,通常情况下(除非您处于一次分配大量内存的位置),对于这些情况,您可能不会专门捕获OutOfMemoryError,而是在主入口点的顶部执行一个
捕获丢弃的
。不,捕获异常和运行时异常
,但几乎从未(从“从未”改为):
错误是Throwable
这表明严重的问题,即
合理应用不应尝试
抓住。大多数这样的错误是错误的
异常情况。ThreadDeath
错误虽然是“正常”情况,但仍然存在
也是Error
的子类,因为大多数
应用程序不应试图捕获
它
注意:
我在这里引用官方的Javadocs。如果您不同意,请告诉Oracle,不要开枪打死messenger:-)如果您想让messenger正常关机,并具体处理此情况
如果您可能需要分配一个大型阵列,并且希望优雅地降低系统的性能,您也可以使用它
编辑:我用来检查流是否损坏的代码示例。此后,我更换了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;
}
}
我做过的唯一一件事就是移动开发。您可以要求用户关闭其他应用程序,以使您的应用程序能够正常工作。但安卓开发并非如此
我看不出你还能对这种情况做什么。可能是一些适当的日志记录或清理。这也不例外;这是一个错误:java.lang.OutOfMemoryError
您可以在它从Throwable下降时捕捉到它:
试一试{
//在这里创建许多对象并将它们隐藏在某个地方
}捕获(OutOfMemory错误){
//释放上述部分(全部)对象
}
但是,除非您正在做一些非常具体的事情(例如,在特定的代码段中分配大量的内容),否则您可能无法捕获它,因为您不知道它将从何处抛出。黄金法则是只捕获您可以处理的错误。如果在OutOfMemory错误之后,您可以做一些有用的事情,那么继续吧。这是您永远不应该发现的错误之一。原因很简单,您将无法在运行时对此执行任何操作。但是,如果您的应用程序经常面临这个错误,那么您应该考虑以下策略来减轻这个问题——
通过添加JVM参数来增加JVM可用的内存
-Xms1024m-Xmx1024m
如果错误仍然存在,那么使用像JProfiler或EclipseMat这样的探查器来分析应用程序使用了多少内存
移动到64位系统并进一步增加JVM内存
这已经被提到过很多次了,但是回复表明一些人对OutOfMemoryError
的这种(常见的)恢复技术感到困惑。查看我的帖子,了解如何执行此操作的演示。正如其他一些答案所指出的,捕获OutOfMemoryError并尝试恢复是一个坏主意。我将尝试解释原因,而不是重复javadoc说您的Error
异常是不可恢复的
事实上,OOME恢复不明智至少有两个坚实的原因:
第一个原因是OOME通常是未经诊断的内存泄漏的结果。如果您的应用程序捕获并尝试恢复,那么泄漏的内存很可能仍然可以访问,因此仍然无法回收。因此,当应用程序开始执行某些操作时,可能会泄漏更多内存。。。然后又碰到了另一个OOME。应用程序迟早会停止运行
由于无法绝对确保应用程序不会泄漏,所以OOME恢复永远不会是一个可靠的答案
第二个原因是,当OOME发生时,有可能会对执行状态造成损害。它可能会导致线程终止,留下其他线程等待将永远不会到达的通知等。它可能发生在更新关键应用程序数据结构或(可能更糟)JVM数据结构的中间。如果您的应用程序随后尝试恢复,它可能会锁定,或者(更糟的是)它可能会继续处理损坏的数据,并产生不可预测的结果
除非你对你的代码库进行法医学分析,否则你永远不能完全确定这种事情不会发生
我不会说你永远都不应该试图从OOME中恢复,但总的来说这是一件冒险的事情。应用程序越复杂,评估风险就越困难
1-这里我说的是捕捉OOME,试图让应用程序像以前一样继续运行;i、 e.恢复应用程序。捕获OOME以执行(或触发)有序关机是另一回事。您真的无法像JVM本身崩溃那样优雅地降级系统。当系统崩溃并出现崩溃转储时,您在Java中无能为力。然而,如果您得到的只是OutOfMemoryError,您可以捕获它并允许系统继续运行。此错误中没有强迫您的系统