list.add(newObject);

}

解决方案:

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

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

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

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

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

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

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

典型场景:

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

类加载器未正确释放(如频繁部署的 Web 应用导致旧类未卸载)。

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

典型场景:

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

类加载器未正确释放(如频繁部署的 Web 应用导致旧类未卸载)。

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

类加载器未正确释放(如频繁部署的 Web 应用导致旧类未卸载)。

示例:

// 使用 CGLib 动态生成大量代理类

Enhancer enhancer = newEnhancer;

while(true) {

enhancer.setSuperclass(OOM.class);

enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args)));

enhancer.create;

}

解决方案:

调整元空间大小(-XX:MaxMetaspaceSize)。

检查类加载器泄漏或动态类生成逻辑。

调整元空间大小(-XX:MaxMetaspaceSize)。

检查类加载器泄漏或动态类生成逻辑。

触发原因:直接内存(Direct Memory,通过 ByteBuffer.allocateDirect分配)耗尽。

典型场景:

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

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

触发原因:直接内存(Direct Memory,通过 ByteBuffer.allocateDirect分配)耗尽。

典型场景:

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

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

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

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

示例:

// 不断申请直接内存

List buffers = newArrayList<>;

while(true) {

buffers.add(ByteBuffer.allocateDirect(1024* 1024)); // 1MB

}

解决方案:

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

调整 -XX:MaxDirectMemorySize。

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

调整 -XX:MaxDirectMemorySize。

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

典型场景:

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

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

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

典型场景:

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

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

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

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

示例:

// 无限创建线程

while(true) {

newThread( -> {

}).start;

}

解决方案:

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

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

修改系统线程数限制。

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

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

修改系统线程数限制。

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

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

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

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

解决方案:

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

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

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

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

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

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

解决方案:

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

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

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

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

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

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

解决方案:

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

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

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

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

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

排查时可通过以下步骤:

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

2、使用工具分析(如 jstat、jmap、VisualVM、MAT)。

3、调整 JVM 参数或优化代码逻辑。返回搜狐,查看更多