JVM中产生OOM(内存溢出)的8种典型情况及解决方案

Java中的OutOfMemoryError(OOM)是当JVM内存不足时抛出的错误。本文将全面剖析JVM中产生OOM的各种情况,包括堆内存溢出、方法区溢出、栈溢出等,并提供详细的诊断方法和解决方案。

一、OOM基础概念


1.1 OOM错误类型

  • Java中的OOM是java.lang.OutOfMemoryError的子类,常见的有:
  • Java heap space:堆空间不足
  • GC Overhead limit exceeded:GC效率低下
  • PermGen space/Metaspace:方法区溢出
  • Unable to create new native thread:线程创建失败
  • Requested array size exceeds VM limit:数组过大
  • Direct buffer memory:直接内存溢出
  • Code cache:代码缓存区满
  • Kill process or sacrifice child:Linux系统级限制

二、堆内存溢出(Java heap space)


2.1 产生原因


当对象需要分配到堆内存时,如果堆内存不足且无法通过GC回收足够空间时抛出。

// 典型示例

public class HeapOOM {public static void main(String[] args) {List<Object> list = new ArrayList<>();while(true) {list.add(new byte[1024*1024]); // 每次分配1MB}}
}


2.2 错误信息

java.lang.OutOfMemoryError: Java heap space


2.3 解决方案


调整堆大小:

-Xms256m -Xmx1024m  # 初始堆256MB,最大堆1GB



内存分析:

使用jmap获取堆转储:

jmap -dump:format=b,file=heap.hprof <pid>


使用MAT/Eclipse Memory Analyzer分析


代码优化:

避免内存泄漏(如静态集合、未关闭资源)
使用对象池重用对象


三、GC开销超限(GC Overhead limit exceeded)


3.1 产生原因


当JVM花费超过98%的时间进行GC,但只恢复了不到2%的堆空间时抛出。

// 典型场景:创建大量生命周期短的对象

public class GCOverheadOOM {public static void main(String[] args) {Map<Key, String> map = new HashMap<>();while(true) {for(int i=0; i<10000; i++) {map.put(new Key(i), "Value"+i);}map.clear(); // 不完全清除}}
}


3.2 错误信息

java.lang.OutOfMemoryError: GC Overhead limit exceeded


3.3 解决方案

  1. 增加堆大小:
    ​
    -Xmx2g -XX:+UseG1GC​

  2. 优化GC策略:
  • 对于大量短生命周期对象,使用G1或ZGC
  • 调整新生代大小:
  • -XX:NewRatio=2  # 新生代占堆的1/3

  1. 代码改进:
  • 减少临时对象创建
  • 使用更高效的数据结构

四、方法区溢出(Metaspace/PermGen)


4.1 产生原因


JDK8前称为PermGen space,JDK8+称为Metaspace,存储类元数据信息。

// 通过动态生成类填满方法区
public class MetaspaceOOM {static class OOMObject {}public static void main(String[] args) {while(true) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OOMObject.class);enhancer.setUseCache(false);enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o, objects));enhancer.create(); // 动态创建类}}
}


4.2 错误信息
 

// JDK7及之前
java.lang.OutOfMemoryError: PermGen space// JDK8+
java.lang.OutOfMemoryError: Metaspace


4.3 解决方案


调整Metaspace大小:

-XX:MaxMetaspaceSize=256m


JDK8前调整PermGen:

-XX:MaxPermSize=128m


减少动态类生成:

缓存动态代理类
限制反射使用


五、线程栈溢出(Unable to create new native thread)


5.1 产生原因


当创建线程数量超过系统限制时发生。

public class ThreadOOM {public static void main(String[] args) {while(true) {new Thread(() -> {try { Thread.sleep(100000); } catch(InterruptedException e) {}}).start();}}
}


5.2 错误信息

java.lang.OutOfMemoryError: Unable to create new native thread


5.3 解决方案


减少线程数量:

使用线程池:

ExecutorService pool = Executors.newFixedThreadPool(100);

调整系统限制:

ulimit -u  # 查看最大线程数
ulimit -u 2048  # 设置最大线程数



减少栈大小:

-Xss256k  # 默认1MB,减少可创建更多线程



六、直接内存溢出(Direct buffer memory)


6.1 产生原因


NIO使用的直接内存(堆外内存)不足时抛出。

public class DirectMemoryOOM {public static void main(String[] args) {// 绕过DirectByteBuffer限制,直接分配内存List<ByteBuffer> buffers = new ArrayList<>();while(true) {buffers.add(ByteBuffer.allocateDirect(1024*1024)); // 1MB}}
}


6.2 错误信息

java.lang.OutOfMemoryError: Direct buffer memory



6.3 解决方案


调整直接内存大小:

-XX:MaxDirectMemorySize=256m


显式回收:

((DirectBuffer)buffer).cleaner().clean();


使用池化技术:

Netty的ByteBuf池


七、数组过大溢出(Requested array size exceeds VM limit)


7.1 产生原因


尝试分配超过JVM限制的数组。

public class ArraySizeOOM {public static void main(String[] args) {int[] arr = new int[Integer.MAX_VALUE]; // 约2^31-1个元素}
}



7.2 错误信息

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


7.3 解决方案
减小数组大小:

分块处理大数据
使用集合替代:

List<Integer> list = new ArrayList<>();


调整数据结构:

使用数据库或文件存储


八、代码缓存溢出(Code cache)


8.1 产生原因


JIT编译的代码填满代码缓存区。

// 通常由大量方法被JIT编译导致

public class CodeCacheOOM {public static void main(String[] args) {// 需要大量方法编译的代码}
}



8.2 错误信息

java.lang.OutOfMemoryError: Code cache



8.3 解决方案
增加代码缓存大小:

-XX:ReservedCodeCacheSize=256m



减少编译阈值:

-XX:CompileThreshold=10000



关闭分层编译:

-XX:-TieredCompilation



九、系统级OOM(Kill process or sacrifice child)


9.1 产生原因
Linux系统的OOM Killer终止进程。

dmesg | grep -i kill


输出示例:

Out of memory: Kill process 12345 (java) score 999 or sacrifice child



9.2 解决方案
增加系统内存
调整OOM Killer策略:

echo -17 > /proc/[pid]/oom_adj


限制容器内存(Docker):

docker run -m 2g my-java-app



十、OOM诊断工具链

OOM诊断工具链
工具用途示例命令
jstat监控内存和GCjstat -gcutil <pid> 1000
jmap堆转储jmap -dump:live,format=b,file=heap.hprof <pid>
jvisualvm可视化分析图形化界面
MAT内存分析分析hprof文件
jcmd多功能工具jcmd <pid> VM.native_memory


十一、OOM预防最佳实践


代码层面:

避免内存泄漏(监听器、静态集合)
及时关闭资源(数据库连接、文件流)
使用WeakReference处理缓存
JVM配置:

# 基础配置示例

-Xms1g -Xmx2g -XX:MaxMetaspaceSize=256m 
-XX:+UseG1GC -XX:MaxGCPauseMillis=200


监控预警:

JMX监控堆内存使用
Prometheus + Grafana监控体系
设置合理的GC日志监控:

-Xlog:gc*:file=gc.log:time:filecount=5,filesize=10M



十二、总结


OOM类型与对应解决方案速查表:

OOM类型相关内存区域典型解决方案
Java heap space增大堆,修复内存泄漏
GC Overhead优化GC策略,减少对象创建
Metaspace/PermGen方法区增大Metaspace,减少动态类生成
Unable to create thread减少线程数,调整-Xss
Direct buffer直接内存增大MaxDirectMemorySize,显式回收
Array size减小数组尺寸,分块处理
Code cacheJIT代码缓存增大ReservedCodeCacheSize
System OOM系统内存增加物理内存,调整OOM Killer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97740.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【IEEE出版、EI检索、往届会后3个月检索】第四届信号处理、计算机网络与通信国际学术会议(SPCNC 2025)

第四届信号处理、计算机网络与通信国际学术会议&#xff08;SPCNC 2025&#xff09;将于2025年12月5-7日于中国武汉召开&#xff08;线上同步&#xff09;。为本次会议旨在齐聚海内外信号处理、计算机网络与通信等计算机领域的专家学者&#xff0c;为相关领域研究和从业人员提供…

Spring boot注解介绍

1. Spring 核心注解Spring Boot 是基于 Spring 框架的&#xff0c;所以核心注解依然适用。✅ 常见核心注解Component表示一个通用组件&#xff0c;Spring 会自动扫描并注入到容器中。Component public class MyComponent {public void sayHello() {System.out.println("He…

撤销回退 情况⼆:已经 add ,但没有 commit

撤销回退 情况⼆&#xff1a;已经 add &#xff0c;但没有 commit add 后还是保存到了暂存区呢&#xff1f;怎么撤销呢&#xff1f; 1 # 向ReadMe中新增⼀⾏代码 2 hyb139-159-150-152:~/gitcode$ vim ReadMe 3 hyb139-159-150-152:~/gitcode$ cat ReadMe 4 hello bit 5 hell…

【Linux笔记】命令行与vim基础

一、Linux命令行基础 1. 基本语法命令空格参数&#xff08;可写可不写&#xff09;空格文件&#xff0c;文件夹&#xff08;可写可不写&#xff09;ls列出文件夹中的内容/opt 根目录下的opt文件夹ls-a all显示出所有文件以及隐藏文件/optls-a如果不写则输出一个点&#xff0c;当…

Redis 的整数集合:像分类收纳盒一样的整数专属存储

目录 一、先懂定位&#xff1a;为什么需要整数集合&#xff1f;&#xff08;衔接哈希表&#xff09; 二、整数集合的结构&#xff1a;像 “贴了规格标签的收纳盒” 1. encoding&#xff1a;收纳盒的 “规格标签”&#xff08;核心&#xff1a;决定格子大小&#xff09; 2. …

Linux 进程状态 — 僵尸进程

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录进…

React 中 key 的作用

React 中 key 的作用是什么&#xff1f; Date: August 31, 2025 Area: 原理key 概念 在 React 中&#xff0c;key 用于识别哪些元素是变化、添加或删除的。 在列表渲染中&#xff0c;key 尤其重要&#xff0c;因为它能提高渲染性能和确保组件状态的一致性。key 的作用 1&#x…

wpf之附加属性

前言 附加属性是 WPF 中一个非常强大和独特的概念。简单来说&#xff0c;它允许一个对象为另一个在其本身类定义中未定义的属性赋值。 1、定义附加属性 定义一个Watermark的附加属性&#xff0c;该属性的作用是将TextBox的附加属性改变时&#xff0c;TextBox的字体颜色改成灰…

深入浅出 RabbitMQ-消息可靠性投递

大家好&#xff0c;我是工藤学编程 &#x1f989;一个正在努力学习的小博主&#xff0c;期待你的关注实战代码系列最新文章&#x1f609;C实现图书管理系统&#xff08;Qt C GUI界面版&#xff09;SpringBoot实战系列&#x1f437;【SpringBoot实战系列】SpringBoot3.X 整合 Mi…

数字化时代,中小企业如何落地数字化转型

大数据时代&#xff0c;各行各业的行业龙头和大型集团都已经开始了数据管理&#xff0c;让数据成为数据资产。但是在我国&#xff0c;中小企业的数量巨大&#xff0c;很多管理者忽视了这一点&#xff0c;今天我们就来聊一聊中小企业的数字化转型。中小企业需要数字化转型首先要…

Unity笔记(九)——画线功能Linerenderer、范围检测、射线检测

写在前面&#xff1a;写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。这里只记录代码知识。十一、画线功能Linerenderer画线功能Linerenderer是Unity提供的画线脚本&#xff0c;创建一个空…

刷题记录(8)string类操作使用

一、仅反转字母 917. 仅仅反转字母 - 力扣&#xff08;LeetCode&#xff09; 简单来说输入字符串&#xff0c;要求你返回所有仅字母位置反转后的字符串。 简单看一个样例加深理解&#xff1a; 前后互换&#xff0c;我想思路基本很明显了&#xff0c;双指针&#xff0c;或者说…

用好AI,从提示词工程到上下文工程

前言 随着 AI 大模型的爆发,提示词工程(prompt engineering ) 一度是用户应用 AI ,发挥 AI 能力最重要、也最应该掌握的技术。 但现在,在 “提示词工程”的基础上,一个更宽泛也更强力的演化概念被提出,也就是本文我们要介绍的 “上下文工程(Context Engineering)” …

计算机Python毕业设计推荐:基于Django+Vue用户评论挖掘旅游系统

精彩专栏推荐订阅&#xff1a;在下方主页&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、项目介绍二、…

⸢ 肆 ⸥ ⤳ 默认安全:安全建设方案 ➭ a.信息安全基线

&#x1f44d;点「赞」&#x1f4cc;收「藏」&#x1f440;关「注」&#x1f4ac;评「论」 在金融科技深度融合的背景下&#xff0c;信息安全已从单纯的技术攻防扩展至架构、合规、流程与创新的系统工程。作为一名从业十多年的老兵&#xff0c;将系统阐述数字银行安全体系的建设…

如何用AI视频增强清晰度软件解决画质模糊问题

在视频制作和分享过程中&#xff0c;画质模糊、细节丢失等问题常常影响观看体验。无论是老旧视频的修复还是低分辨率素材的优化&#xff0c;清晰度提升都成为用户关注的重点。借助专业的AI技术&#xff0c;这些问题可以得到有效解决。目前市面上存在多种解决方案&#xff0c;能…

Linux92 shell:倒计时,用户分类

问题 while IFS read -r line;doootweb kk]# tail -6 /etc/passwd user1r4:x:1040:1040::/home/user1r4:/bin/bash useros20:x:1041:1041::/home/useros20:/bin/bash useros21:x:1042:1042::/home/useros21:/bin/bash useros22:x:1043:1043::/home/useros22:/bin/bash useros23…

LinkedList源码解析

1. 数据结构设计 (1) 节点结构 LinkedList 的核心是双向链表节点 Node&#xff1a; private static class Node<E> {E item; // 存储的元素Node<E> next; // 后继节点Node<E> prev; // 前驱节点Node(Node<E> prev, E element, Node<E&g…

语雀批量导出知识库

使用工具&#xff1a;yuque-dl 参考文档&#xff1a; GitHub - gxr404/yuque-dl: yuque 语雀知识库下载 Yuque-DL&#xff1a;一款强大的语雀资源下载工具_语雀文档怎么下载-CSDN博客

电子电气架构 --- 当前企业EEA现状(下)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…