Java 捕捉出内存错误

Java 捕捉出内存错误,java,out-of-memory,Java,Out Of Memory,在java中捕获内存不足错误(java.lang.OutOfMemoryError)有什么意义吗?是。以下是一些有意义的例子: 如果您想通过优雅地关闭程序来处理它 如果要向用户显示问题或记录错误 根据您的设计,您甚至可以清除内存并恢复工作状态 但是,请注意,通常情况下(除非您处于一次分配大量内存的位置),对于这些情况,您可能不会专门捕获OutOfMemoryError,而是在主入口点的顶部执行一个捕获丢弃的。不,捕获异常和运行时异常,但几乎从未(从“从未”改为): 错误是Throwable

在java中捕获内存不足错误(
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,您可以捕获它并允许系统继续运行。此错误中没有强迫您的系统