【问题标题】:How to handle OutOfMemoryError in multi threading? [duplicate]如何处理多线程中的 OutOfMemoryError? [复制]
【发布时间】:2017-12-21 19:33:59
【问题描述】:

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

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

【问题讨论】:

  • 提示:小心适应变通方法。当您的设计/代码被破坏并包含错误时,那么花在无助于修复该错误的事情上的每一分钟都是有风险的投资。
  • @GhostCat 感谢您的提示,但有时环境是问题所在。例如,我们在较新的 Linux 线程限制较低(systemd 的默认值)中遇到了问题。所以我们有漂亮的代码,根本就没有在其他环境中运行。

标签: java multithreading out-of-memory


【解决方案1】:

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

要解决您的问题,您应该首先尝试查明这些内存错误的根源,例如通过记录它们,或使用性能/内存分析工具。在这些情况下,enforcing a core-dump 也很有用,然后您可以在它发生的那一刻分析根本原因。

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

【讨论】:

  • 它们也可以像处理任何其他错误一样处理,唯一的例外是您需要在 GC 能够释放足够内存以便您的代码运行时捕获的唯一异常。所以在声明持有大量内存的变量的范围之外的某个地方。
  • 在现实生活中的架构将确保没有 OOM 错误(例如在非常大的对象上使用弱对象链接,或在磁盘上/按顺序处理)。不需要调用 gc,JVM 会自动尝试释放内存来运行,如果失败则抛出 OOM。
  • 您建议在现实生活中捕获此异常。那么你建议在那个 catch() 子句中加入什么?
  • 照常捕获和记录。唯一的区别是您必须如上所述捕获超出范围,以便内存可用。一般来说,我在最外层范围内有类似 catch (Error e) { log.error("General failure: ", e); } 的子句。这样我就知道出了什么可怕的问题,但服务器一般(但不是单个任务)可以继续。
  • 我明白了;但仍然:从与该服务器交互的个人用户的角度来看 - 那里发生了什么?您是否会“计算”此类事件?这样当你在 1 分钟内出现 5 个这样的错误时,你可能仍然会关机?
猜你喜欢
  • 2010-10-05
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多