检测内存不足错误

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

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

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

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

我们启用了-XX:+HeapDumpOnOutOfMemoryError ,但是我没有将此视为此问题的解决方案,因为它是为其他内容设计的 – 当发生这种情况时它不提供Java回调。

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

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

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

根据post有一篇文章 ,Scorpion已经给出了一个链接。

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

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

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

我们启用了-XX:+ HeapDumpOnOutOfMemoryError,但是我没有将此视为此问题的解决方案,因为它是为其他内容设计的 – 当发生这种情况时它不提供Java回调。

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

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

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