15

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

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

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

我看到的一种可能的情况是字节码操作(例如在 顶部附加某种方面OutOfMemoryError),但是我不确定这是否是正确的方法,或者这在一般情况下是否可行。

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

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

4

4 回答 4

6

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

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

于 2012-07-16T18:12:16.577 回答
3

一篇基于Scorpion 已经给出链接的帖子的文章。

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

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

幸运的是,还有另一个阈值,“收集使用阈值”,以及一个相应的事件,它会在垃圾回收后立即根据内存消耗触发。当您收到该事件时,您可以更加确信自己的内存不足。

于 2015-01-07T10:04:57.170 回答
0

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

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

字节码检测是可能的 - 但很难。 HPjmeter 的监控工具能够预测未来的 OOM(带有警告)——但仅限于基于 HP-UX/Itanium 的系统。您可以专用一个守护线程来计算进程中的已用内存,并在超过此值时触发警报,但实际上您并没有解决问题。

于 2012-07-16T17:59:16.533 回答
0

您可以使用静态捕获任何和所有未捕获的异常Thread.setDefaultUncaughtExceptionHandler. 当然,如果有人捕获所有 Throwables,它也无济于事。(我不认为任何事情都会发生,尽管使用 OOME 我怀疑你会得到级联效应,直到有问题的try块之外的东西爆炸为止。)希望线程会释放足够的内存以供异常处理程序工作;当您尝试处理它们时,OOM 错误确实会成倍增加。

于 2012-07-16T19:17:41.127 回答