【问题标题】:Java try catch - out of memory [duplicate]Java try catch - 内存不足[重复]
【发布时间】:2014-03-05 18:40:55
【问题描述】:

try catch 在捕获内存不足异常方面有多好?我没有任何编写在低级别管理自己的内存的软件的经验,但我可以想象一种方法来做到这一点。

我不知道 Java 实际处理内存异常的方式。管理内存的程序是否可能内存不足?我什么时候可以尝试捕获内存不足的异常并且它无法捕获异常?

谢谢!

【问题讨论】:

标签: java


【解决方案1】:

您不必担心作为捕获可投掷物的一部分而发生的任何隐式分配,本身。抓住它们总是可能。 JVM 甚至会保留预先分配的 OOM 错误实例,以便在发生故障时使用,以便它们自己永远不会分配失败。

但是,很可能还有次要问题:

  • 众所周知,任何分配都可能是压死骆驼的最后一根稻草,因此您可能不知道代码将在何处引发 OOM 错误。它甚至可能发生在与您正在执行内存消耗工作的线程完全不同的线程中,从而导致 JVM 的完全不同部分崩溃。
  • 根据您在捕获它时要执行的操作,您可能会分配更多内存(例如 LogRecordStringBuilder,后者甚至可能作为语法字符串连接的一部分隐式发生),这可能会再次耗尽内存。

这些问题仅适用于“正常方式”耗尽内存的情况。也就是说,通过分配大量“正常”对象。相反,如果内存耗尽的操作是单个分配,例如 10 GB 数组,那么它们不会造成问题。

【讨论】:

    【解决方案2】:

    try catch 在捕获内存不足异常方面有多好?

    它在一个层面上工作得很好......但在另一个层面上它可能是有风险的,和/或徒劳的。见下文。

    管理内存的程序是否可能内存不足?

    管理内存的“程序”是垃圾收集器。 AFAIK,它总是有足够的内存用于自己的目的。如果不是这样,它就别无选择,只能让 JVM 硬崩溃。

    我什么时候可以尝试捕获内存不足的异常并且它无法捕获异常?

    仅当 JVM 崩溃时。或者,如果 OOME 被抛出到与您试图捕获它的线程堆栈不同的线程堆栈上。


    好吧,那么为什么捕捉 OOME 是有风险和/或徒劳的。

    第一个原因是 OOME 可以在任何线程堆栈上抛出而没有任何警告。当您捕获异常时,处理程序(通常)无法知道“堆栈”发生了什么,以及它究竟是如何失败的。因此,它无法知道应用程序的执行状态是否已损坏或受损。 (线程是否正在更新一些重要的东西?它是否要通知其他线程......而线程现在永远不会收到通知?)

    第二个原因是 OOME 通常是 Java 存储泄漏的结果……由不应该做的“挂在”对象上引起的。如果您捕获 OOME 并尝试恢复...当问题是由泄漏引起的...有可能仍然可以访问有问题的对象,并且很快就会出现另一个 OOME。换句话说,您的应用程序可能会陷入不断抛出 OOME 并从中恢复的状态。充其量这会降低性能......因为JVM通常在OOME之前做的最后一件事是执行完整的(停止世界)垃圾收集。这需要很长时间。

    请注意,这并不是说您永远不应该捕获 OOME。实际上,捕获 OOME、报告它然后关闭通常是一个不错的策略。

    不,冒险/徒劳的事情是抓住 OOME,然后尝试恢复并继续运行。

    【讨论】:

      【解决方案3】:

      在java中Out Of Memory不是一个例外,它是一个错误。您可以在程序级别执行任何操作,但这是系统限制。您可以通过增加默认堆内存大小来逃避它。

      export JVM_ARGS="-Xmx1024m -XX:MaxPermSize=256m"
      

      【讨论】:

        【解决方案4】:

        OutOfMemory 是错误而非异常。错误专门用于区分程序可以捕获并希望恢复的事物与不可恢复的低级错误。

        只有当您认为可以采取措施从该异常/错误中恢复时,您才能捕获某些内容,而您无法从 OutOfMemory 中恢复。

        【讨论】:

          【解决方案5】:


          首先,内存不足是java中的Error而不是Exception。我们可以使用try-catch构造或throws子句来处理java中的异常。

          Error 和 Exception 类都扩展了 Throwable 类。但是 Error 是不可恢复的条件,Exception 是可以处理的。

          根据您的情况,请通过 java 中的垃圾收集。

          【讨论】:

          • 这不是真的。所有Throwables 都是可捕获的,错误就是这样。
          • 只有按照惯例才会处理异常,并且只有按照惯例才能不理会错误。你可以catch(Throwable t) 而只是不在乎,这太可怕了。
          • @Dolda2000 请举个例子,否则我不同意你的看法..
          • 自己试试吧:try {throw new OutOfMemoryError();} catch(OutOfMemoryError e) {System.out.println("Caught!");}
          • 只是为了记录,异常和错误之间的实际区别是错误通常不意味着被捕获,而异常是。
          猜你喜欢
          • 2013-09-10
          • 1970-01-01
          • 2013-03-30
          • 2023-01-25
          • 2014-12-18
          • 1970-01-01
          • 2011-06-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多