面试时如何回答有哪些OOM类型?

摘要:大家好,我是小富~ 面试官:OOM类型有哪些? 你:就是老年代放不下了嘛! 面试官:等消息吧! OOM(Out Of Memory) 错误有多种类型,每种类型对应不同的内存区域或触发场景。以下是常见的 OOM 类型及其产生原因: 1. ja
大家好,我是小富~ 面试官:OOM类型有哪些? 你:就是老年代放不下了嘛! 面试官:等消息吧! OOM(Out Of Memory) 错误有多种类型,每种类型对应不同的内存区域或触发场景。以下是常见的 OOM 类型及其产生原因: 1. java.lang.OutOfMemoryError: Java heap space 触发原因:堆内存(存放对象实例)不足,无法分配新对象。 典型场景: 内存泄漏:对象被无意长期引用(如静态集合、未关闭的资源),无法被 GC 回收。 堆大小不足:JVM 堆参数(-Xmx)设置过小,或程序需要处理的数据量超出预期。 大对象分配:一次性申请超大对象(如大数组)。 示例: // 不断向集合中添加对象导致堆溢出 List<Object> list = new ArrayList<>(); while (true) { list.add(new Object()); } 解决方案: 检查内存泄漏(使用 jmap + MAT 分析堆转储)。 调整堆大小(-Xmx 和 -Xms)。 优化代码逻辑,减少对象生命周期。 2. java.lang.OutOfMemoryError: Metaspace(Java 8+)或 PermGen space(Java 7-) 触发原因:元空间(Metaspace)或永久代(PermGen)内存不足,用于存储类元数据、方法信息等。 典型场景: 动态生成大量类(如使用 CGLib、反射、动态代理)。 类加载器未正确释放(如频繁部署的 Web 应用导致旧类未卸载)。 示例: // 使用 CGLib 动态生成大量代理类 Enhancer enhancer = new Enhancer(); while (true) { enhancer.setSuperclass(OOM.class); enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args))); enhancer.create(); } 解决方案: 调整元空间大小(-XX:MaxMetaspaceSize)。 检查类加载器泄漏或动态类生成逻辑。 3. java.lang.OutOfMemoryError: Direct buffer memory 触发原因:直接内存(Direct Memory,通过 ByteBuffer.allocateDirect() 分配)耗尽。 典型场景: 频繁申请直接内存但未及时释放(需依赖 System.gc() 或 Cleaner 机制)。 JVM 直接内存参数(-XX:MaxDirectMemorySize)设置过小。 示例: // 不断申请直接内存 List<ByteBuffer> buffers = new ArrayList<>(); while (true) { buffers.add(ByteBuffer.allocateDirect(1024 * 1024)); // 1MB } 解决方案: 检查直接内存使用代码,确保及时释放。 调整 -XX:MaxDirectMemorySize。 4. java.lang.OutOfMemoryError: Unable to create new native thread 触发原因:操作系统限制线程数量,无法创建新线程。 典型场景: 线程数超过系统限制(如 Linux 的 ulimit -u)。 每个线程的栈内存(-Xss)设置过大,导致总内存占用超出。 示例: // 无限创建线程 while (true) { new Thread(() -> { try { Thread.sleep(1000000); } catch (InterruptedException e) {} }).start(); } 解决方案: 减少线程数(使用线程池)。 调整 -Xss 减小线程栈大小。 修改系统线程数限制。 5. java.lang.OutOfMemoryError: Requested array size exceeds VM limit 触发原因:尝试分配超过 JVM 限制的数组(通常接近 Integer.MAX_VALUE)。 典型场景:错误计算数组长度,如 new int[Integer.MAX_VALUE]。
阅读全文