jvm内存溢出是多种内存区域耗尽触发的不同异常:堆溢出(java heap space)因对象分配失败且gc无效;元空间溢出(metaspace)由类元数据过多导致;直接内存溢出(direct buffer memory)源于nio direct buffer超限;栈相关异常包括stackoverflowerror和unable to create new native thread;gc开销超限表示gc效率崩溃;代码缓存区满则影响jit编译。

JVM 内存溢出不是单一错误,而是多种内存区域耗尽后触发的不同异常,每种对应不同的内存结构、成因和表现形式。
堆内存溢出(Java heap space)
最常见类型,发生在对象实例分配区域。当新对象无法在堆中获得足够空间,且 GC 无法回收出可用内存时抛出。
- 典型报错:
java.lang.OutOfMemoryError: Java heap space - 常见诱因:大对象集中创建(如加载超大文件)、集合类长期持有无用对象(静态 List 缓存未清理)、内存泄漏积累
- 关键特征:堆使用率持续升高,频繁 Full GC 后仍无法释放足够空间
元空间溢出(Metaspace)
取代了早期 JDK 的永久代(PermGen),用于存储类元数据(类定义、常量池、方法信息等)。动态类生成过多或类加载器未卸载时易触发。
- 典型报错:
java.lang.OutOfMemoryError: Metaspace - 常见诱因:大量使用反射、CGLIB 动态代理、JSP 编译、OSGi 框架、微服务频繁热部署
- 关键特征:应用运行一段时间后突然失败,尤其在反复加载/卸载类的场景下
直接内存溢出(Direct buffer memory)
由 NIO 的 ByteBuffer.allocateDirect() 分配,不受 JVM 堆参数控制,依赖操作系统物理内存和 -XX:MaxDirectMemorySize 限制。
手动 Telegram 斜杠命令,用于查看 Codex 状态及使用情况。用户发送 /codex_usage、/codex_usage default、/codex_usage all 等时触发。
- 典型报错:
java.lang.OutOfMemoryError: Direct buffer memory - 常见诱因:Netty 等框架未及时释放 direct buffer、大量短生命周期 direct buffer 创建、未设置或低估 MaxDirectMemorySize
- 关键特征:堆内存充足但程序仍崩溃;
jstat显示堆使用正常,jmap -histo:live查不到大对象
栈内存相关异常(StackOverflowError / OutOfMemoryError)
虚拟机栈和本地方法栈区域问题,虽严格意义上不属“OOM”子类,但同属内存资源耗尽范畴。
-
StackOverflowError:线程调用深度超限(如无限递归),栈帧数量超出限制 -
java.lang.OutOfMemoryError: unable to create new native thread:系统无法为新线程分配栈空间,通常因线程数过多或-Xss设置过大导致进程级内存耗尽 - 关键区别:前者是单线程栈溢出,后者是整个 JVM 进程线程资源枯竭
GC 开销超限(GC overhead limit exceeded)
一种“软性”内存不足信号,表示 GC 已陷入恶性循环——花费 98% 时间回收,却只释放不到 2% 堆空间。
- 典型报错:
java.lang.OutOfMemoryError: GC overhead limit exceeded - 常见诱因:大量短生命周期小对象持续生成(如字符串拼接、无界缓存)、老年代碎片化严重、堆大小与对象生命周期不匹配
- 关键特征:应用响应明显变慢,日志中密集出现 GC 日志,但堆使用率未必达 100%
代码缓存区满(CodeCache)
JIT 编译器将热点代码编译为本地机器码后存放的区域。长期运行或大量动态生成代码(如 Groovy 脚本)可能填满。
- 典型报错:
java.lang.OutOfMemoryError: Compressed class space或java.lang.OutOfMemoryError: requested code cache size exceeded - 可通过
-XX:ReservedCodeCacheSize和-XX:+PrintCodeCache监控 - 现象:JIT 编译停用,性能下降;部分 JDK 版本会降级为解释执行










