Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

  • Java IO

  • JVM

    • JVM概述
    • JVM基础

    • 类加载机制

    • 运行时内存

      • Java堆
      • 方法区与元空间
      • 虚拟机栈本地方法栈与程序计数器
      • 对象创建与内存布局
      • 直接内存
      • OOM分类与定位
        • 1. Java heap space
        • 2. GC overhead limit exceeded
        • 3. Metaspace
        • 4. Direct buffer memory
        • 5. unable to create native thread
        • 6. Requested array size exceeds VM limit
        • 7. OOM 自动转储参数
        • 8. 阶段小结
        • 9. OOM 定位决策树
        • 10. OOM 现场保护
        • 11. 不同 OOM 的修复方向
        • 12. Tips 快问快答
    • 垃圾回收

    • 执行引擎与优化

    • 工具与问题排查

    • 调优实践与面试

目录

OOM分类与定位

OutOfMemoryError 不是一种问题,而是一组问题。不同 OOM 发生在不同内存区域,定位方式也不同。

# 1. Java heap space

java.lang.OutOfMemoryError: Java heap space

表示 Java 堆空间不足。

常见原因:

  • 大集合无限增长。
  • 缓存没有淘汰。
  • 一次性加载大文件。
  • 内存泄漏。
  • 流量突增导致对象创建过快。
  • 堆配置过小。

定位方式:

  • 开启 OOM 自动 dump。
  • 使用 MAT、JProfiler、VisualVM 分析堆转储。
  • 查看最大对象、引用链、GC Roots。

# 2. GC overhead limit exceeded

java.lang.OutOfMemoryError: GC overhead limit exceeded

表示 JVM 花大量时间做 GC,但回收效果很差。

本质通常还是堆压力过大。

常见原因:

  • 内存泄漏。
  • 堆太小。
  • 老年代占满。
  • 大量对象存活。

# 3. Metaspace

java.lang.OutOfMemoryError: Metaspace

表示元空间不足。

常见原因:

  • 大量动态生成类。
  • 类加载器泄漏。
  • 热部署未释放。
  • 代理类、脚本类不断增长。

定位方式:

  • 查看类加载数量。
  • 分析类加载器。
  • 使用 jcmd VM.classloader_stats。
  • 检查动态代理和热部署逻辑。

# 4. Direct buffer memory

java.lang.OutOfMemoryError: Direct buffer memory

表示直接内存不足。

常见原因:

  • NIO direct buffer 创建过多。
  • Netty ByteBuf 泄漏。
  • 堆外内存限制过小。
  • 引用未释放导致 Cleaner 无法回收。

定位方式:

  • 检查 -XX:MaxDirectMemorySize。
  • 使用 Native Memory Tracking。
  • 查看框架堆外内存指标。
  • 开启 Netty leak detector。

# 5. unable to create native thread

java.lang.OutOfMemoryError: unable to create native thread

表示无法创建新的系统线程。

原因可能是:

  • 线程数过多。
  • 系统线程数限制。
  • 进程内存不足。
  • 每个线程栈太大。
  • 容器限制。

定位方式:

  • 查看线程数量。
  • 查看 -Xss。
  • 查看系统 ulimit。
  • 查看容器资源限制。
  • 分析线程池是否失控。

# 6. Requested array size exceeds VM limit

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

表示请求创建的数组超过 JVM 支持的最大长度。

常见于:

  • 计算数组长度溢出。
  • 一次性读取超大文件。
  • 错误地构造超大集合。

# 7. OOM 自动转储参数

生产环境常配置:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/dump

注意 dump 文件可能很大,要保证磁盘空间充足,并注意敏感数据保护。

# 8. 阶段小结

定位 OOM 的第一步是看错误信息,判断发生在哪个内存区域。堆 OOM 看对象引用链,元空间 OOM 看类加载器,直接内存 OOM 看堆外分配,线程 OOM 看线程数和系统限制。不要一看到 OOM 就盲目加 -Xmx。

# 9. OOM 定位决策树

出现 OOM / 进程被杀
  │
  ├─ JVM 抛出 OutOfMemoryError?
  │   │
  │   ├─ Java heap space
  │   │   └─ heap dump -> MAT -> GC Roots
  │   │
  │   ├─ GC overhead limit exceeded
  │   │   └─ 看 GC 日志 + 堆对象存活
  │   │
  │   ├─ Metaspace
  │   │   └─ 看类加载器、动态类、元空间参数
  │   │
  │   ├─ Direct buffer memory
  │   │   └─ 看直接内存、Netty、NMT
  │   │
  │   └─ unable to create native thread
  │       └─ 看线程数、Xss、ulimit、容器限制
  │
  └─ 没有 JVM OOM,容器 OOMKilled?
      └─ 看进程 RSS、cgroup、堆外、线程栈、系统事件

这棵树的重点是:先分类型,再找证据。不同 OOM 的处理方式完全不同。

# 10. OOM 现场保护

生产环境建议:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/dump
-XX:ErrorFile=/data/logs/hs_err_pid%p.log

同时要注意:

  • dump 目录磁盘空间。
  • dump 文件敏感数据。
  • OOM 后是否自动重启导致现场丢失。
  • 容器 OOMKilled 时 JVM 可能来不及 dump。

# 11. 不同 OOM 的修复方向

OOM 类型 临时缓解 根因修复
Java heap space 扩堆、限流、重启 修复泄漏、限制缓存、流式处理
Metaspace 增大元空间 修复类加载器泄漏、减少动态类
Direct buffer memory 增大直接内存、重启 释放 ByteBuf、复用 buffer
native thread 降低线程数、扩资源 线程池治理、降低 -Xss
容器 OOMKilled 扩容或降堆 做总内存预算

# 12. Tips 快问快答

Q:OOM 后 dump 一定能生成吗?

A:不一定。容器 OOMKilled、磁盘不足、权限问题都可能导致 dump 失败。

Q:GC overhead limit exceeded 是 GC 问题吗?

A:表面是 GC 开销过高,本质通常是堆中存活对象太多或堆太小。

Q:OOM 一定要重启吗?

A:线上恢复可能需要重启,但重启前尽量保留 dump、日志和指标,否则根因会丢失。

Q:为什么加大堆后问题过几天又出现?

A:如果根因是泄漏,加堆只是延迟爆发,不是修复。

上次更新: 2026/06/24, 16:03:01
直接内存
垃圾回收概述

← 直接内存 垃圾回收概述→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式