检测内存不足错误

时间:2012-07-16 16:13:34

标签: java exception exception-handling out-of-memory

我想为我的系统提供一种检测是否发生了内存不足异常的方法。此练习的目的是通过JMX公开此标志并相应地执行操作(例如,通过在监视系统上配置相关警报),否则这些错误将被忽视几天。

天真的方法是为每个线程设置一个uncaught exception handler并检查引发的异常是否为OutOfMemoryError的实例并设置相关标志。但是,由于以下原因,这种方法并不现实:

  • 异常可能发生在任何地方,包括第三方库。我无法阻止他们抓住Throwable并为自己保留。
  • 库可以生成自己的线程,我无法为这些线程强制执行未捕获的异常处理程序。

我看到的一个可能的场景是字节码操作(例如在OutOfMemoryError之上附加某种方面),但我不确定这是否正确,或者这是否可行。

我们已启用-XX:+HeapDumpOnOutOfMemoryError,但我不认为这是针对此问题的解决方案,因为它是为其他内容设计的 - 并且在发生这种情况时它不会提供Java回调。

有人这样做过吗?你会如何解决它或建议解决它?欢迎任何想法。

4 个答案:

答案 0 :(得分:5)

您可以使用内存不足警告系统;这http://www.javaspecialists.eu/archive/Issue092.html可以成为一种灵感。您可以配置在某个内存阈值(例如80%)被破坏后调用的侦听器 - 您可以使用此调用来开始采取纠正措施。

我们使用类似的东西,当组件的内存阈值达到80%时我们暂停组件的服务并开始清理操作;只有当使用的内存低于另一个可配置的值阈值时,组件才会返回。

答案 1 :(得分:3)

基于articlethe post Scorpion已经提供了链接。

该技术再次基于使用MemoryPoolMXBean并订阅超过"内存阈值"事件,但它与原始帖子中描述的略有不同。

作者声明,当您订阅普通"内存阈值超过"事件,有可能发生误报"。想象一下当内存消耗高于阈值时的情况,但很快就会执行垃圾收集,之后会释放大量内存。事实上,这种情况在现实世界的应用中非常普遍。

幸运的是,还有另一个阈值,"集合使用阈值"以及相应的事件,在垃圾收集后立即根据内存消耗触发。当您收到该事件时,您可以更加自信地耗尽内存。

答案 2 :(得分:0)

  

我们启用了-XX:+ HeapDumpOnOutOfMemoryError,但是我没有看到这个   作为这个问题的解决方案,因为它是为其他东西设计的 -   当发生这种情况时,它不提供Java回调。

此标志应该是您需要的全部内容。将生成的堆转储文件的输出目录设置在您定期检查的某个已知位置。回调对你没用。如果内存不足,则无法保证回调代码有足够的内存来执行!您所能做的就是收集数据并使用外部程序来分析内存不足的原因。任何尝试恢复过程都会产生更大的问题。

字节码仪器是可能的 - 但很难。 HPjmeter's监控工具能够预测未来的OOM(有警告) - 但仅限于基于HP-UX / Itanium的系统。您可以将一个守护程序线程专门用于计算正在使用的内存,并在超出此值时触发警报,但实际上您并未解决该问题。

答案 3 :(得分:0)

你可以使用静态Thread.setDefaultUncaughtExceptionHandler.捕获任何和所有未捕获的异常当然,如果有人捕获所有Throwables,它就无济于事。 (我认为不会有任何事情,但是对于OOME我怀疑你会得到级联效果,直到有问题的try块之外的事情爆发为止。)希望线程能够为异常释放足够的内存处理工作;当你试图处理它们时,OOM错误往往会成倍增加。