一文写全OOM

在Java应用程序中,常见的OOM(OutOfMemoryError)类型主要包括以下七种

1,Java Heap Space OOM

  • 触发原因:堆内存(存放对象实例)不足,无法分配新对象。

  • 典型场景

(1)内存泄漏:对象被无意长期引用(如静态集合、未关闭的资源),无法被 GC 回收。

(2)堆大小不足:JVM 堆参数(-Xmx)设置过小,或程序需要处理的数据量超出预期。

(3)大对象分配:一次性申请超大对象(如大数组)。

示例:

// 不断向集合中添加对象导致堆溢出
List<Object> list = new ArrayList<>();
while (true) {
    list.add(new Object());
}

解决方案

  • 检查内存泄漏(使用 jmap + MAT 分析堆转储)。

  • 调整堆大小(-Xmx 和 -Xms)。

  • 优化代码逻辑,减少对象生命周期。

2,PermGen Space OOM (仅Java 7及更早版本)

  • 触发原因:元空间(Metaspace)或永久代(PermGen)内存不足,用于存储类元数据、方法信息等。

  • 典型场景

(1)动态生成大量类(如使用 CGLib、反射、动态代理)。

(2)类加载器未正确释放(如频繁部署的 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() 分配)耗尽。

  • 典型场景

(1)频繁申请直接内存但未及时释放(需依赖 System.gc() 或 Cleaner 机制)。

(2)JVM 直接内存参数(-XX:MaxDirectMemorySize)设置过小。

示例:

// 不断申请直接内存
List<ByteBuffer> buffers = new ArrayList<>();
while (true) {
    buffers.add(ByteBuffer.allocateDirect(1024 * 1024)); // 1MB
}

解决方案

  • 检查直接内存使用代码,确保及时释放。

  • 调整 -XX:MaxDirectMemorySize

4,Thread OOM

  • 错误信息java.lang.OutOfMemoryError: Unable to create new native thread

  • 触发原因:操作系统限制线程数量,无法创建新线程。

  • 典型场景

(1)线程数超过系统限制(如 Linux 的 ulimit -u)。

(2)每个线程的栈内存(-Xss)设置过大,导致总内存占用超出。

示例:

// 无限创建线程
while (true) {
    new Thread(() -> {
        try { Thread.sleep(1000000); } catch (InterruptedException e) {}
    }).start();
}

解决方案

  • 减少线程数(使用线程池)。

  • 调整 -Xss 减小线程栈大小。

  • 修改系统线程数限制

5,Requested array size exceeds VM limit

错误信息:java.lang.OutOfMemoryError: Requested array size exceeds VM limit

  • 触发原因:尝试分配超过 JVM 限制的数组(通常接近 Integer.MAX_VALUE)。

  • 典型场景:错误计算数组长度,如 new int[Integer.MAX_VALUE]

解决方案

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

6,GC Overhead Limit Exceeded

解决方案

  • 错误信息java.lang.OutOfMemoryError: GC overhead limit exceeded

  • 触发原因:GC 频繁执行但回收效率极低(如 98% 时间用于 GC,仅回收 2% 内存)。

  • 典型场景:堆内存几乎被占满,且存在大量无法回收的对象(内存泄漏)。

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

7,CodeCache(JIT 编译代码缓存溢出)

  • 触发原因:JIT 编译器生成的本地代码占满代码缓存区。

  • 典型场景:高频动态编译大量方法(如复杂的热点代码)。

解决方案

  • 调整代码缓存大小(-XX:ReservedCodeCacheSize)。

  • 关闭分层编译(-XX:-TieredCompilation)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东皋长歌

你的鼓励是我分享的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值