我查了很多地方,都没有找到 JVM 由于 OOM 而死掉的原因。我没有考虑操作系统 killer 。为了提供一些背景信息,我有一个正在运行的 Java 应用程序,它开始耗尽内存,我知道它可能在 JVM 开始终止线程后继续存在。
但是,我见过它在第一次 OOM 后运行了 30 多分钟,并且一直以这种无响应状态运行,它可能会恢复,也可能不会恢复。但是,我也看到在复制相同的步骤来触发 OOM 后,它在第一次 OOM 后立即崩溃。系统在内存方面没有问题,问题只是出在 JVM 上。所以,我的问题是:
- 在 OOM 期间,JVM 会发生什么情况,导致它可能崩溃或永久处于无响应状态?
- JVM 如何终止线程?是随机的吗?
最佳答案
从技术上讲,OutOfMemoryError
是“另一个可抛出的错误”,因此它可能会或可能不会杀死它被抛出的线程,具体取决于该线程如何处理其异常.
例如,如果它在最低级别有一个 catch (Error e)
block ,那么它可以在运行时“承受”很多问题。
因此,如果您的 OutOfMemoryError
仅在优雅地处理此类错误的线程中抛出,那么您的系统可以继续正常工作。
但这也是 OutOfMemoryError
的 2 个不寻常属性发挥作用的地方:
- 它基本上可以在分配内存的任何地方抛出,并且确切它将被抛出的位置是如此不可预测,以至于看起来是随机的。它经常被抛出在分配最多内存的地方,但这并不总是正确的。
- 由于错误条件的性质,它表示在尝试处理异常时很可能再次遇到完全相同的错误(例如,在尝试生成有关耗尽内存的日志消息时,您可能会耗尽内存)内存)。这种递归性质使得可靠地处理
OOME
变得异常困难。
如果您希望应用程序中真正能够应对 OOM,则必须确保所有线程要么妥善处理 OutOfMemoryError
,要么当他们不这样做时正确重新启动(通过看门狗或类似的东西)。这通常很难做到,尤其是在使用任何创建自己线程的库时。
因此,您问题的tl;dr答案是:
- “这取决于”您的线程如何处理异常
- 线程将因无法处理初始异常或无法处理在尝试处理初始异常时发生的异常而被终止。哪条线程受到攻击是不可预测的,以至于看起来是随机的。
关于java - JVM 如何因 OOM 异常而死掉?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61460194/