Java尝试赶上内存

时间:2014-02-08 07:21:14

标签: java

尝试捕获内存异常有多好?我没有任何编写低级别软件管理自己内存的经验,但我可以想象一种方法。

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

谢谢!

5 个答案:

答案 0 :(得分:2)

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

然而,可能存在次要问题:

  • 任何分配都可能是打破骆驼背部的众所周知的稻草,所以你可能不知道你的代码会在哪里抛出OOM错误。它甚至可能发生在与您正在进行内存消耗的工作完全不同的线程中,从而导致JVM完全不同的部分崩溃。
  • 根据你抓到它时要做的事情,你可能会分配更多的内存(例如LogRecordStringBuilder,后者甚至可能隐含地作为一部分发生语法字符串连接),可能会再次耗尽内存。

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

答案 1 :(得分:1)

  

尝试捕获内存异常有多好?

它在一个级别上运行得很好......但在另一个级别它可能有风险和/或徒劳。见下文。

  

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

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

  

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

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


好的,那么为什么要抓住OOME风险和/或徒劳无功。

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

第二个原因是OOME通常是Java存储泄漏的结果......由于某些东西“挂在”对象上而不应该这样做。如果你抓到一个OOME并试图恢复......当问题是由泄漏造成的......很可能仍然可以获得有问题的对象,而另一个OOME很快就会跟进。换句话说,您的应用程序可能会陷入持续投掷并从OOME恢复的状态。这至多会破坏性能...因为在OOME之前JVM通常执行的最后一件事就是执行完整(停止世界)垃圾收集。这需要很长时间。

请注意,并不是说你永远不应该抓住OOME。实际上,捕获OOME,报告然后关闭通常是一个很好的策略。

不,有风险/无效的事情是抓住OOME,然后尝试恢复并继续跑步。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

OutOfMemory是错误而非例外。错误专门用于区分可以捕获并希望通过程序恢复到无法恢复的低级错误的事物。

如果你认为可以从这个异常/错误中恢复,你只能抓住一些东西,你无法从OutOfMemory中恢复。

答案 4 :(得分:-4)


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

Error和Exception类都扩展了Throwable类。但错误是不可恢复的条件,并且Exception是可以使用的。

根据您的情况,请参阅java中的垃圾收集。