面试被问:OOM 类型有哪些?怎么答?
大家好,我是小富~
面试官:OOM 类型有哪些?
你:就是老年代放不下了嘛!
面试官:等消息吧!
OOM(Out Of Memory) 错误有多种类型,每种类型对应不同的内存区域或触发场景。以下是常见的 OOM 类型及其产生原因:
1. java.lang.OutOfMemoryError: Java heap space
触发原因:堆内存(存放对象实例)不足,无法分配新对象。
典型场景:
内存泄漏:对象被无意长期引用(如静态集合、未关闭的资源),无法被 GC 回收。
堆大小不足:JVM 堆参数(
-Xmx
)设置过小,或程序需要处理的数据量超出预期。大对象分配:一次性申请超大对象(如大数组)。
示例:
解决方案:
检查内存泄漏(使用
jmap
+MAT
分析堆转储)。调整堆大小(
-Xmx
和-Xms
)。优化代码逻辑,减少对象生命周期。
2. java.lang.OutOfMemoryError: Metaspace
(Java 8+)或 PermGen space
(Java 7-)
触发原因:元空间(Metaspace)或永久代(PermGen)内存不足,用于存储类元数据、方法信息等。
典型场景:
动态生成大量类(如使用 CGLib、反射、动态代理)。
类加载器未正确释放(如频繁部署的 Web 应用导致旧类未卸载)。
示例:
解决方案:
调整元空间大小(
-XX:MaxMetaspaceSize
)。检查类加载器泄漏或动态类生成逻辑。
3. java.lang.OutOfMemoryError: Direct buffer memory
触发原因:直接内存(Direct Memory,通过
ByteBuffer.allocateDirect()
分配)耗尽。典型场景:
频繁申请直接内存但未及时释放(需依赖
System.gc()
或Cleaner
机制)。JVM 直接内存参数(
-XX:MaxDirectMemorySize
)设置过小。
示例:
解决方案:
检查直接内存使用代码,确保及时释放。
调整
-XX:MaxDirectMemorySize
。
4. java.lang.OutOfMemoryError: Unable to create new native thread
触发原因:操作系统限制线程数量,无法创建新线程。
典型场景:
线程数超过系统限制(如 Linux 的
ulimit -u
)。每个线程的栈内存(
-Xss
)设置过大,导致总内存占用超出。
示例:
解决方案:
减少线程数(使用线程池)。
调整
-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、使用工具分析(如 jstat
、jmap
、VisualVM
、MAT
)。
3、调整 JVM 参数或优化代码逻辑。
等被裁员在学习?赶紧的吧!
版权声明: 本文为 InfoQ 作者【程序员小富】的原创文章。
原文链接:【http://xie.infoq.cn/article/15fccfabce8ff78f1d4bc7f0f】。文章转载请联系作者。
评论