类型一:Java heap space(堆内存溢出)
java.lang.OutOfMemoryError: Java heap space
这是最常见的 OOM 类型,意思是堆内存不够用了。
可能的原因:
- 堆内存设置太小
- 内存泄漏:对象无法被回收,越积越多
- 突然创建了超大对象或大量对象
类型二:GC overhead limit exceeded(GC 开销超限)
java.lang.OutOfMemoryError: GC overhead limit exceeded
这个 OOM 的意思是:GC 占用了太多时间,却回收不了多少内存。
JDK 的默认阈值是:GC 时间超过 98%,但回收的内存不到 2%,就会抛出这个错误。
通常这是内存泄漏的"前兆"——堆内存快满了,GC 频繁执行但效果甚微,最后彻底撑爆。
类型三:Metaspace(元空间溢出)
java.lang.OutOfMemoryError: Metaspace
JDK 8 之后,永久代被元空间取代,元空间使用的是本地内存。如果元空间溢出,说明加载的类太多了。
可能的原因:
- 元空间设置太小
- 动态生成的类太多(比如 CGLIB 动态代理、反射、JSP 等)
- 类加载器泄漏
类型四:Direct buffer memory(直接内存溢出)
java.lang.OutOfMemoryError: Direct buffer memory
直接内存溢出,通常和 NIO 有关。
Java 的 NIO 可以使用 DirectByteBuffer 直接分配堆外内存,这部分内存不受堆大小限制,但受限于物理内存。如果直接内存用太多,就会报这个错。
常见于使用 Netty、Mina 等 NIO 框架的场景。
类型五:unable to create new native thread(无法创建新线程)
java.lang.OutOfMemoryError: unable to create new native thread
这个 OOM 的意思是:创建线程失败了。
每个线程都需要占用一定的栈内存,当线程数量太多时,系统没有足够的资源来创建新线程。
可能的原因:
- 线程池配置不合理,最大线程数设太大
- 线程泄漏:线程创建了没销毁,越积越多
- 系统限制:操作系统对进程的最大线程数有限制
类型六:StackOverflowError(栈溢出)
java.lang.StackOverflowError
严格来说这不是 OOM,但也是常见的内存相关错误。
栈溢出通常是因为方法调用层次太深,比如递归没有正确的退出条件。
评论
欢迎留下反馈,评论发布后会立即显示。