Java 如何处理多线程中的OutOfMemoryError?

Java 如何处理多线程中的OutOfMemoryError?,java,multithreading,out-of-memory,Java,Multithreading,Out Of Memory,我们在Swing应用程序或大量计算中使用重多线程。有时,应用程序可能会在OOME上运行,无法再创建任何本机线程。我完全理解应用程序必须意识到这一点,从设计上看,这是不好的,但它不能100%避免。问题是,在这种情况下,JVM完全丢失了,因为它无法处理错误,并且系统的行为不可预测。通常我们会记录每个内存错误,然后通过-XX:onAutofmemoryError=“kill-9%p”重新启动应用程序,但这显然不起作用。另一方面,JVM不再有控制权,这有点令人沮丧。那么,解决这类问题的好办法是什么呢 P

我们在Swing应用程序或大量计算中使用重多线程。有时,应用程序可能会在OOME上运行,无法再创建任何本机线程。我完全理解应用程序必须意识到这一点,从设计上看,这是不好的,但它不能100%避免。问题是,在这种情况下,JVM完全丢失了,因为它无法处理错误,并且系统的行为不可预测。通常我们会记录每个内存错误,然后通过-XX:onAutofmemoryError=“kill-9%p”重新启动应用程序,但这显然不起作用。另一方面,JVM不再有控制权,这有点令人沮丧。那么,解决这类问题的好办法是什么呢


PS:我不寻找像扩展系统进程限制或通过Xss减少线程堆栈大小这样的解决方案。我正在寻找一种处理一般错误的方法。

JVM可以完美地控制OutOfMemoryErrors,并且能够优雅地处理它,但不能优雅地处理它的是您的程序。您可以像处理其他错误一样捕获和处理OutOfMemoryError,只是大多数程序从来不会这样做

要解决您的问题,您应该首先尝试查明这些内存错误的根源,例如通过记录它们,或者使用性能/内存分析工具。在这些情况下也很有用,这样您就可以在事件发生时分析根本原因


最后,需要重新设计应用程序,通过限制使用的内存量来避免OOM错误。这可以通过测试程序可以正常处理多少线程并强制执行该限制来实现,也可以通过在创建新线程之前检查可用内存来实现。此外,架构更改可能会有所帮助,但您没有发布有关内部结构的详细信息,因此我无法在此给出任何建议。

提示:在使用变通方法时要小心。当您的设计/代码被破坏并包含一个bug时,那么花在不利于修复该bug的事情上的每一分钟都是一项风险投资。@GhostCat感谢您的提示,但有时环境是问题所在。例如,我们在较新的Linux线程限制为低(默认为systemd)时遇到了一个问题。因此,我们有漂亮的代码,只是没有在其他环境中运行。它们可以像处理任何其他错误一样处理,只有当GC能够释放足够的内存以便代码可以运行时,您需要捕获的例外。因此,在声明包含大量内存的变量的范围之外的某个地方。在现实生活中,体系结构将确保没有OOM错误(比如在真正大的对象上使用弱对象链接,或者在磁盘上/顺序地处理)。不需要调用gc,JVM将自动尝试释放内存以运行,如果失败,则抛出OOM。您建议在现实生活中捕获此异常。那么,您建议在catch()子句中添加什么呢?像往常一样捕获并记录。唯一的区别是,您必须捕获上述范围之外的内容,以便内存可用。一般来说,我在最外层的作用域中有一个类似于
catch(Error e){log.Error(“general failure:,e);}
的子句。这是因为我知道有些地方出了严重的问题,但是服务器(而不是单个任务)可以继续;但是:从单个用户与服务器交互的角度来看,那里发生了什么?你有没有做过“统计”这样的事情;所以当你在一分钟内出现5个这样的错误时,你可能仍然关机?