面试题:JVM 有那几种情况会产生 OOM(内存溢出)?

Java虚拟机(JVM)在运行过程中可能会遇到多种原因导致的内存溢出(OutOfMemoryError,简称OOM)。以下是几种常见的OOM情况及其产生原因:

  1. Java堆空间不足(Java heap space)
    • 当创建对象时,如果Java堆中没有足够的空间来分配新的对象,并且垃圾收集器也无法提供足够的额外空间时,就会抛出java.lang.OutOfMemoryError: Java heap space。这通常是因为应用程序创建了大量的对象,超出了堆的最大容量限制。
  2. 永久代/元空间不足(PermGen/Metaspace)
    • 在JDK 7及之前版本中,使用的是“永久代”(Permanent Generation),而在JDK 8及之后版本则改用了“元空间”(Metaspace)。
      当加载类的数量过多或者单个类非常庞大,导致永久代或元空间耗尽资源时,会抛出相应的错误:java.lang.OutOfMemoryError: PermGen space 或 java.lang.OutOfMemoryError: Metaspace
  3. 方法区内存不足(Method Area)
    • 方法区用于存储已被虚拟机加载的类信息、常量、静态变量等数据。如果方法区无法为新加载的类分配空间,则可能导致OOM错误。
  4. 直接内存不足(Direct Buffer Memory)
    • 使用java.nio.ByteBuffer.allocateDirect()分配的直接缓冲区属于堆外内存。如果申请的直接内存超过了系统可用的最大值,将会触发java.lang.OutOfMemoryError: Direct buffer memory
  5. 栈溢出(Stack Overflow)
    • 如果一个线程请求的栈深度大于JVM允许的最大深度,比如递归调用过深,会导致java.lang.StackOverflowError。虽然这不是严格意义上的OOM,但它与内存管理密切相关。
  6. 无法创建新的本地线程(Unable to create new native thread)
    • 当操作系统不允许JVM创建更多线程,通常是由于达到了操作系统的线程数限制或者是每个线程栈大小设置过大,从而导致总栈空间超过系统可承受范围,这时会抛出java.lang.OutOfMemoryError: unable to create new native thread

每种OOM错误都可能指向不同的问题根源,因此解决这些问题需要针对性地调整JVM参数、优化代码结构或是检查是否有内存泄漏等问题。理解这些错误背后的机制有助于更好地进行故障排查和性能调优。

THE END
喜欢就支持一下吧
点赞15 分享