Java JVM如何因OOM异常而死亡?

Java JVM如何因OOM异常而死亡?,java,out-of-memory,Java,Out Of Memory,我调查了很多地方,没有找到JVM因OOM而死亡的原因。我不考虑操作系统杀手。为了提供一些上下文,我有一个Java应用程序正在运行,它开始耗尽内存,我知道它可能在JVM开始杀死线程后继续存在 但是,我看到它在第一次OOM后运行了30多分钟,并且它一直在这种无响应状态下运行,它可能会恢复,也可能不会恢复。但是,我也看到它在复制触发OOM的相同步骤后,在第一个OOM之后崩溃。系统在内存方面很好,问题在于JVM。因此,我的问题是: 在OOM期间JVM会发生什么情况,导致其崩溃或永久处于无响应状态 JVM

我调查了很多地方,没有找到JVM因OOM而死亡的原因。我不考虑操作系统杀手。为了提供一些上下文,我有一个Java应用程序正在运行,它开始耗尽内存,我知道它可能在JVM开始杀死线程后继续存在

但是,我看到它在第一次OOM后运行了30多分钟,并且它一直在这种无响应状态下运行,它可能会恢复,也可能不会恢复。但是,我也看到它在复制触发OOM的相同步骤后,在第一个OOM之后崩溃。系统在内存方面很好,问题在于JVM。因此,我的问题是:

  • 在OOM期间JVM会发生什么情况,导致其崩溃或永久处于无响应状态
  • JVM如何杀死线程?是随机的吗

  • 从技术上讲,
    OutOfMemoryError
    只是“另一个可丢弃的错误”,因此它可能会或可能不会杀死抛出它的线程,这取决于该线程如何处理其异常

    例如,如果它在最低级别有一个
    catch(Error e)
    块,那么它可以在仍然运行的情况下“承受”很多问题

    因此,如果您的
    OutOfMemoryError
    只被抛出到处理类似错误的线程中,那么您的系统可以继续正常工作

    但这也是
    OutOfMemoryError
    的两个不寻常属性发挥作用的地方:

  • 它基本上可以被抛出到内存分配的任何地方,而它将被抛出的确切位置是如此不可预测,以至于看起来是随机的。它经常被扔到分配最多内存的地方,但这决不是永远正确的
  • 由于它所表示的错误条件的性质,在尝试处理异常时很可能再次遇到完全相同的错误(例如,您可能在尝试生成关于内存不足的日志消息时内存不足)。这种递归特性使得可靠地处理
    OOME
    非常困难
  • 因此,tl;dr您的问题的答案如下:

  • “这取决于”线程如何处理异常
  • 如果未能处理初始异常或未能处理在尝试处理初始异常时发生的异常,线程将被终止。哪个线程被击中是如此不可预测以至于看起来是随机的

  • 我建议为您的问题提供更多的上下文,因为您不应该从内存中获得任何异常不确定JVM在任何正常情况下(我认为是这样)是否“曾经”预期会崩溃(可能有一些奇怪的原因)。我猜可能会比较经常发生的是线程中发生的OOM,它永远不会被
    catch
    块捕获。未触发的异常/错误会在堆栈跟踪中冒泡,杀死发出它们的线程。如果这种情况发生在唯一/最后一个非守护进程线程上,那么JVM就会存在,就像它总是存在一样。这可能是您的情况吗?或者,如果您想了解内部结构,您可以签出序列I通过减少最大堆导致OOM,因为我想知道它为什么崩溃,有时不崩溃。GPI得到了这个想法,可能是这样,但我找不到任何具体的文档。非常感谢!:)@极好:不客气。但请注意,在堆栈溢出时不需要(实际上不鼓励)使用“非常感谢”注释。感谢贡献者的首选方式是通过投票(并在适当情况下将答案标记为已接受)。仅供将来参考;-)