0

0

Java虚拟机OOM解析

雪夜

雪夜

发布时间:2025-06-25 09:58:16

|

458人浏览过

|

来源于php中文网

原创

[注:本文内容摘选自作者之前的博客]

对于以Java为核心的企业级应用开发,Java虚拟机(JVM)是项目架构的核心。只有深入理解其内存分配和垃圾回收机制,才能在项目建设中得心应手,无论是基于当前流行的微服务架构(如Spring Cloud或Dubbo),还是即将(或已经)流行的服务网格体系。

不多废话,先看一张Java虚拟机的内存体系结构图:

Java虚拟机OOM解析 注:本文主要基于Oracle JDK体系进行阐述

此图主要针对Java Lang Out Of Memory Error异常进行了适当调整,因为核心问题和要素可以通过此图展示。本文主要解析OOM异常,若想深入了解Java虚拟机的相关知识,可参考官方文档。

立即学习Java免费学习笔记(深入)”;

当我们的应用程序因Java虚拟机内存分配异常时,会抛出java.lang.OutOfMemoryError错误。以下结合实际项目经验,总结了常见的OOM原因及其解决方法,如有遗漏或错误,欢迎补充指正。

1、Java Heap Space

此情况表明当堆内存(Heap Space)没有足够空间存放新创建的对象时,会抛出java.lang.OutOfMemoryError: Java heap space错误。

原因分析

Java heap space错误的常见原因包括以下几类:

1、请求创建一个超大对象,通常是一个大数组

2、超出预期的访问量/数据量,通常是上游系统请求流量飙升

3、过度使用终结器(Finalizer),该对象没有立即被GC

4、内存泄漏(Memory Leak),大量对象引用没有释放,JVM无法自动回收,常见于使用File等资源未回收

解决方案

针对大多数情况,通常只需通过-Xmx参数增加JVM堆内存空间即可。如果问题仍然存在,可以参考以下情况进行进一步处理:

1、如果是超大对象,检查其合理性,例如是否一次性查询了数据库全部结果,而没有限制结果数量。

2、如果是业务峰值压力,可以考虑增加机器资源或进行限流降级。

3、如果是内存泄漏,需要找到持有的对象,优化代码设计。

2、GC overhead limit exceeded

此情况为JDK1.6新增的错误类型。如果没有此异常,会发生什么?垃圾回收释放的2%可用内存空间会迅速被填满,迫使GC再次执行,导致频繁执行GC操作,服务器会因为频繁的GC操作达到100%的使用率,运行变慢,应用系统会出现卡顿现象,通常几毫秒可完成的操作,现在需要更长时间,甚至几分钟才能完成。

原因分析

1、垃圾回收可用空间较小

2、频繁执行GC操作,使得资源使用率较高

解决方案

1、增加heap堆内存

2、增加内存后错误依旧,获取heap内存快照,使用Eclipse MAT工具,找出内存泄露并进行修复

3、优化代码以使用更少的内存或重用对象,而不是创建新的对象,从而减少垃圾收集器的运行次数。如果代码中在循环中创建了许多临时对象,应该尝试重用它们

4、升级JDK到1.8,至少也是1.7,并使用G1 GC垃圾回收算法

5、优化代码

3、Unable to create new native thread

每个Java线程都需要占用一定的内存空间,当JVM向底层操作系统请求创建一个新的native线程时,如果没有足够的资源分配就会报此类错误。

原因分析

JVM向OS请求创建native线程失败,就会抛出Unable to create new native thread错误,常见原因包括以下几类:

1、线程数超过操作系统最大线程数ulimit限制

2、线程数超过kernel.pid_max(只能重启)

3、native内存不足

解决方案

1、升级配置,为机器提供更多的内存

2、降低Java Heap Space大小

3、修复应用程序的线程泄漏问题

4、限制线程池大小

5、使用-Xss参数减少线程栈的大小

6、调高OS层面的线程最大数:执行ulimit -a查看最大线程数限制,使用ulimit -u xxx调整最大线程数限制

4、Out of swap space?

此错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)组成。当程序运行时请求的虚拟内存溢出时,会报Out of swap space错误。

原因分析

此错误出现的常见原因包括以下几类:

1、地址空间不足

2、物理内存已耗光

Orz企业网站管理系统 双语版
Orz企业网站管理系统 双语版

Orz企业网站管理系统整合了企业网站所需要的大部分功能,并在其基础上做了双语美化。压缩包内有必须的图片psd源文件,方便大家修改。 Orz企业网站管理系统功能: 1.动态首页 2.中英文双语同后台管理 3.产品具有询价功能 4.留言板功能 5.动态营销网络 6.打印功能 7.双击自动滚动 Orz企业网站管理系统安装 1、请将官方程序包解压后上传至您的虚拟主机即可正常使用; 2、后台管理面板登录:

下载

3、应用程序的本地内存泄漏(native leak),例如不断申请本地内存却不释放

4、执行jmap -histo:live 命令,强制执行Full GC;如果几次执行后内存明显下降,则基本确认为Direct ByteBuffer问题

解决方案

根据错误原因可以采取如下解决方案:

1、升级地址空间为64 bit

2、使用Arthas检查是否为Inflater/Deflater解压缩问题,如果是,则显式调用end方法

3、Direct ByteBuffer问题可以通过启动参数-XX:MaxDirectMemorySize调低阈值

4、升级服务器配置/隔离部署,避免争用

5、Kill process or sacrifice child

有一种内核作业(Kernel Job)称为Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer会对所有进程进行评分,然后将评分较低的进程“杀死”,具体的评分规则可以参考Surviving the Linux OOM Killer。

不同于其他的OOM错误,Kill process or sacrifice child错误不是由JVM层面触发的,而是由操作系统层面触发的。

原因分析

1、默认情况下,Linux内核允许进程申请的内存总量大于系统可用内存,通过这种“错峰复用”的方式可以更有效地利用系统资源

2、然而,这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存,然后导致其他进程没有可用内存。此时,系统将自动激活OOM Killer,寻找评分低的进程,并将其“杀死”,释放内存资源

解决方案

1、升级服务器配置/隔离部署,避免争用

2、OOM Killer调优

6、Requested array size exceeds VM limit

JVM限制了数组的最大长度,此错误表示程序请求创建的数组超过最大长度限制。JVM在为数组分配内存前,会检查要分配的数据结构在系统中是否可寻址,通常为Integer.MAX_VALUE-2。

此类问题比较罕见,通常需要检查代码,确认业务是否需要创建如此大的数组,是否可以拆分为多个块,分批执行。

7、Direct buffer memory

Java允许应用程序通过Direct ByteBuffer直接访问堆外内存,许多高性能程序通过Direct ByteBuffer结合内存映射文件(Memory Mapped File)实现高速IO。

原因分析

Direct ByteBuffer的默认大小为64 MB,一旦使用超出限制,就会抛出Direct buffer memory错误。

解决方案

1、Java只能通过ByteBuffer.allocateDirect方法使用Direct ByteBuffer,因此,可以通过Arthas等在线诊断工具拦截该方法进行排查

2、检查是否直接或间接使用了NIO,如netty,jetty等

3、通过启动参数-XX:MaxDirectMemorySize调整Direct ByteBuffer的上限值

4、检查JVM参数是否有-XX:+DisableExplicitGC选项,如果有就去掉,因为该参数会使System.gc()失效

5、检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用sun.misc.Cleaner的clean()方法来主动释放被Direct ByteBuffer持有的内存空间

6、内存容量确实不足,升级配置

8、Permgen space

此错误表示永久代(Permanent Generation)已用满,通常是因为加载的class数目太多或体积太大。

原因分析

永久代存储对象主要包括以下几类:

1、加载/缓存到内存中的class定义,包括类的名称,字段,方法和字节码

2、常量池

3、对象数组/类型数组所关联的class

4、JIT编译器优化后的class信息[PermGen的使用量与加载到内存的class的数量/大小正相关]

解决方案

根据Permgen space报错的时机,可以采用不同的解决方案,如下所示:

1、程序启动报错,修改-XX:MaxPermSize启动参数,调大永久代空间

2、应用重新部署时报错,很可能是应用没有重启,导致加载了多份class信息,只需重启JVM即可解决

3、运行时报错,应用程序可能会动态创建大量class,而这些class的生命周期很短暂,但是JVM默认不会卸载class,可以设置-XX:+CMSClassUnloadingEnabled和-XX:+UseConcMarkSweepGC这两个参数允许JVM卸载class

9、Metaspace

原因分析

JDK1.8使用Metaspace替换了永久代(Permanent Generation),此错误表示Metaspace已被用满,通常是因为加载的class数目太多或体积太大。

解决方案

此类问题的原因与解决方法跟Permgen space非常类似,可以参考上文。需要特别注意的是调整Metaspace空间大小的启动参数为-XX:MaxMetaspaceSize。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

154

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

88

2026.01.26

Java 微服务与 Spring Cloud 实战
Java 微服务与 Spring Cloud 实战

本专题讲解 Java 微服务架构的开发与实践,重点使用 Spring Cloud 实现服务注册与发现、负载均衡、熔断与限流、分布式配置管理、API Gateway 和消息队列。通过实际项目案例,帮助开发者理解 如何将传统单体应用拆分为高可用、可扩展的微服务架构,并有效管理和调度分布式系统中的各个组件。

50

2026.02.05

eclipse教程
eclipse教程

php中文网为大家带来eclipse教程合集,eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。php中文网还为大家带来eclipse的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

193

2023.06.14

eclipse怎么设置中文
eclipse怎么设置中文

eclipse设置中文的方法:除了设置界面为中文外,你还可以为Eclipse添加中文插件,以便更好地支持中文编程。例如,你可以安装EBNF插件来支持中文变量名,或安装Chinese Helper来提供中文帮助文档。本专题为大家提供eclipse设置中文相关的各种文章、以及下载和课程。

805

2023.07.24

c语言编程软件有哪些
c语言编程软件有哪些

c语言编程软件有GCC、Clang、Microsoft Visual Studio、Eclipse、NetBeans、Dev-C++、Code::Blocks、KDevelop、Sublime Text和Atom。更多关于c语言编程软件的问题详情请看本专题的文章。php中文网欢迎大家前来学习。

620

2023.11.02

Eclipse版本号有哪些区别
Eclipse版本号有哪些区别

区别:1、Eclipse 3.x系列:Eclipse的早期版本,包括3.0、3.1、3.2等;2、Eclipse 4.x系列:Eclipse的最新版本,包括4.0、4.1、4.2等;3、Eclipse IDE for Java Developers等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

179

2024.02.23

eclipse和idea有什么区别
eclipse和idea有什么区别

eclipse和idea的区别:1、平台支持;2、内存占用;3、插件系统;4、智能代码提示;5、界面设计;6、调试功能;7、学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

149

2024.02.23

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

1

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.8万人学习

Java 教程
Java 教程

共578课时 | 78.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号