面试被问:OOM类型有哪些?怎么答?

大家好,我是小富~

面试官:OOM类型有哪些?
你:就是老年代放不下了嘛!
面试官:等消息吧!

OOM(Out Of Memory) 错误有多种类型,每种类型对应不同的内存区域或触发场景。以下是常见的 OOM 类型及其产生原因:


1. java.lang.OutOfMemoryError: Java heap space

  • 触发原因:堆内存(存放对象实例)不足,无法分配新对象。
  • 典型场景
    • 内存泄漏:对象被无意长期引用(如静态集合、未关闭的资源),无法被 GC 回收。
    • 堆大小不足 :JVM 堆参数(-Xmx)设置过小,或程序需要处理的数据量超出预期。
    • 大对象分配:一次性申请超大对象(如大数组)。

示例

java 复制代码
// 不断向集合中添加对象导致堆溢出
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 应用导致旧类未卸载)。

示例

java 复制代码
// 使用 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)设置过小。

示例

java 复制代码
// 不断申请直接内存
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)设置过大,导致总内存占用超出。

示例

java 复制代码
// 无限创建线程
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]

解决方案

  • 检查数组长度计算逻辑,使用合理的数据结构。

6. java.lang.OutOfMemoryError: GC Overhead limit exceeded

  • 触发原因:GC 频繁执行但回收效率极低(如 98% 时间用于 GC,仅回收 2% 内存)。
  • 典型场景:堆内存几乎被占满,且存在大量无法回收的对象(内存泄漏)。

解决方案

  • 检查内存泄漏或优化 GC 策略(如调整堆大小、更换垃圾回收器)。

7. java.lang.OutOfMemoryError: CodeCache(JIT 编译代码缓存溢出)

  • 触发原因:JIT 编译器生成的本地代码占满代码缓存区。
  • 典型场景:高频动态编译大量方法(如复杂的热点代码)。

解决方案

  • 调整代码缓存大小(-XX:ReservedCodeCacheSize)。
  • 关闭分层编译(-XX:-TieredCompilation)。

总结

OOM 的根本原因是 JVM 内存区域不足资源耗尽,需结合错误类型分析具体内存区域(堆、元空间、直接内存等)。

排查时可通过以下步骤:

1、确定 OOM 类型(通过错误日志)。

2、使用工具分析(如 jstatjmapVisualVMMAT)。

3、调整 JVM 参数或优化代码逻辑。

等被裁员在学习?赶紧的吧!

相关推荐
一水鉴天几秒前
整体设计 修订 之1 三“先”之“基” 与范畴重构:康德先验哲学的批判性程序化实现
java·人工智能·算法
F-ine3 分钟前
若依cloud集训总结
java·spring cloud
IT_陈寒27 分钟前
Python性能优化必知必会:7个让代码快3倍的底层技巧与实战案例
前端·人工智能·后端
小猪咪piggy34 分钟前
【JavaEE】(18) MyBatis 进阶
java·java-ee·mybatis
多读书19336 分钟前
JavaEE进阶-文件操作与IO流核心指南
java·java-ee
叫我阿柒啊37 分钟前
Java全栈工程师的实战面试:从基础到微服务的全面解析
java·数据库·vue.js·spring boot·微服务·前端开发·全栈开发
练习时长两年半的Java练习生(升级中)41 分钟前
从0开始学习Java+AI知识点总结-27.web实战(Maven高级)
java·学习·maven
拾忆,想起1 小时前
Redis发布订阅:实时消息系统的极简解决方案
java·开发语言·数据库·redis·后端·缓存·性能优化
艾莉丝努力练剑1 小时前
【C语言16天强化训练】从基础入门到进阶:Day 14
java·c语言·学习·算法
BioRunYiXue1 小时前
FRET、PLA、Co-IP和GST pull-down有何区别? 应该如何选择?
java·服务器·网络·人工智能·网络协议·tcp/ip·eclipse