检测内存不足错误
我想为我的系统提供一种检测是否发生内存不足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错误往往会成倍增加。
- 如何在Java中处理StackOverflowError?
- java.lang.ArrayIndexOutOfBoundsException:0 – 大于索引的数组?
- javax.naming.NoInitialContextException – Java
- Mac OS无法打开TopCoder Arena
- 在构造函数中尝试/捕获 – 推荐的做法?
- java.util.ConcurrentModificationException&iteration?
- MediaSession finishBroadcast()exception
- java sqlexception没有找到合适的驱动程序
- CopyOnWriteArrayList抛出CurrentModificationException