如何处理多线程中的OutOfMemoryError错误?

14 浏览
0 Comments

如何处理多线程中的OutOfMemoryError错误?

我们在Swing应用程序或大量计算中使用了大量的多线程。偶尔会发生应用程序遇到OOME(Out of Memory Error)无法再创建任何本地线程的情况。我完全理解应用程序必须意识到这一点,并且这是设计上的问题,但是不能百分之百避免。问题在于,在这种情况下,JVM完全迷失了,因为它无法处理错误,系统的行为变得不可预测。通常情况下,我们会记录每个内存错误,并通过-XX:OnOutOfMemoryError=\"kill -9 %p\"重新启动应用程序,但是由于明显的原因,这种方法不起作用。另一方面,JVM没有任何控制权,有点让人沮丧。那么有什么好的方法可以解决这种问题呢?\n附注:我不寻求像扩展系统进程限制或通过Xss减小线程堆栈大小之类的解决方案。我正在寻找一种处理这类问题的方法。

0
0 Comments

多线程中出现OutOfMemoryError的原因是程序没有优雅地处理该错误。解决这个问题的方法是首先定位内存错误的根源,例如通过记录日志或使用性能/内存分析工具。此外,在这些情况下强制执行核心转储可能会很有用,这样您可以在发生错误时分析根本原因。

最后,重新设计应用程序是必要的,以避免OOM错误,方法是通过限制使用的内存量。可以通过测试程序能够优雅处理多少个线程,然后强制执行该限制来实现这一点,或者在创建新线程之前检查可用内存。此外,架构更改可能也有所帮助,但是您没有提供有关内部结构的详细信息,因此我无法在这方面提供建议。

与其他错误一样,也可以像处理其他错误一样处理它们,唯一的例外是您需要在GC能够释放足够内存以使您的代码运行的时候捕获。因此,需要在声明持有大量内存的变量的作用域之外的某个位置进行捕获。

在实际应用中,架构将确保没有OOM错误(例如在真正大的对象上使用弱对象链接,或者在磁盘/顺序处理上)。不需要调用gc,JVM将自动尝试释放内存以进行功能并在失败时抛出OOM。

你建议在实际应用中捕获这个异常。那么你建议在catch()子句中放入什么?

像往常一样捕获并记录日志。唯一的区别是你需要在上述作用域之外捕获,以便释放内存。通常情况下,我在最外层作用域中有一个类似于catch (Error e) { log.error("General failure: ", e); }的子句。这样我就知道出现了严重错误,但是服务器(而不是单个任务)可以继续运行。

我明白了;但是从与服务器交互的个别用户的角度来看 - 在那里会发生什么?您是否会对此类事件进行“计数”;例如,如果在1分钟内出现5个这样的错误,您是否会关闭服务器?

与个别用户的会话将被终止,但无论如何都没有简单的方法来继续该会话。这个错误被称为错误,是因为它是代码中的错误,而不是应该处理的状态。如何处理这个错误取决于应用程序以及它是否对其正常运行至关重要。从技术上讲,应用程序可以继续运行(大部分正常),但重新启动服务器听起来是个好主意。但是,这样的错误应始终进行调查。

正如我在问题中所指出的,通过线程引起的OOM是一个特殊问题。当达到限制时,您无法处理任何东西,也无法转储堆。很抱歉明确地说,但是Java对此没有完美的控制。

我一直在管理几个Java项目,这些项目在大量使用线程的同时存在内存问题,但从未遇到过任何与捕获OOM有关的问题。我假设此错误不仅涉及线程。

0