深入解析发生 OOM 的三大场景

news2024/9/22 21:16:31

深入解析 OOM 的三大场景

    • 什么是 OOM?
    • 一、堆内存溢出 ( Heap OOM )
      • 原因分析
      • 解决方案
    • 二、栈内存溢出(Stack OOM)
      • 原因分析
      • 解决方案
    • 三、方法区内存溢出(Metaspace OOM)
      • 原因分析
      • 解决方案

在Java应用程序开发中,OutOfMemoryError(OOM)是一个令人头痛的问题。当JVM中的内存无法满足应用程序的需求时,就会抛出这个错误。本文将深入探讨OOM的三大场景:堆内存溢出、方法区内存溢出和栈内存溢出,并分析它们的原因,提供相应的实战解决方案。

什么是 OOM?

OOM 的全称是 Out Of Memory,那我们的内存区域有哪些会发生 OOM 呢?我们可以从内存区域划分图上,看一下彩色部分
在这里插入图片描述

可以看到除了程序计数器,其他区域都有OOM溢出的可能。但是最常见的还是发生在堆内存溢出、方法区内存溢出和栈内存溢出,主要是在堆上。

在这里插入图片描述

另外,我们常说的 OOM 异常,其实是 Error

在这里插入图片描述

一、堆内存溢出 ( Heap OOM )

Java 堆用于存储对象实例,我们只要不断的创建对象,并且保证 GC Roots 到对象之间有可达路径来避免 GC 清除这些对象,那随着对象数量的增加,总容量触及堆的最大容量限制后就会产生内存溢出异常。

Java 堆内存的 OOM 异常是实际应用中最常见的内存溢出异常。

/**
 * JVM参数:-Xmx10m
 */
public class JavaHeapSpaceDemo {
 
    static final int SIZE = 100 * 1024 * 1024;
 
    public static void main(String[] a) {
        int[] i = new int[SIZE];
    }
}

代码试图分配容量为 100M 的 int 数组,如果指定启动参数 -Xmx10m,分配内存就不够用,就类似于将 XXXL 号的对象,往 S 号的 Java heap space 里面塞。

原因分析

  1. 对象过多:应用程序创建了大量的对象,并且这些对象长时间存活,导致堆内存不足。
  2. 内存泄漏:应用程序中存在内存泄漏,即长时间无法释放不再使用的对象,导致堆内存持续占用。
  3. 超出预期的访问量/数据量:通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值

解决方案

针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理:

  1. 优化代码:减少不必要的对象创建,避免过大的集合和数组。
  2. 如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接
  3. 如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。

二、栈内存溢出(Stack OOM)

栈内存溢出通常与线程的执行和递归调用有关。

public class StackOverflowErrorDemo {
 
    public static void main(String[] args) {
        javaKeeper();
    }
 
    private static void javaKeeper() {
        javaKeeper();
    }
}

原因分析

  1. 递归调用过深(最常见原因):递归算法实现不当,导致递归深度过大,超出了线程栈的大小限制。
  2. 线程创建过多:应用程序创建了大量的线程,并且每个线程的栈内存分配过多,导致系统资源耗尽。

解决方案

  1. 修复引发无限递归调用的异常代码, 通过程序抛出的异常堆栈,找出不断重复的代码行,按图索骥,修复无限递归 Bug

  2. 排查是否存在类之间的循环依赖

  3. 通过 JVM 启动参数 -Xss 增加线程栈内存空间, 某些正常使用场景需要执行大量方法或包含大量局部变量,这时可以适当地提高线程栈空间限制

三、方法区内存溢出(Metaspace OOM)

方法区内存溢出通常与类的加载和元数据的存储有关。

JDK 1.8 之前会出现 Permgen space,该错误表示永久代(Permanent Generation)已用满,通常是因为加载的 class 数目太多或体积太大。随着 1.8 中永久代的取消,就不会出现这种异常了。

Metaspace 是方法区在 HotSpot 中的实现,它与永久代最大的区别在于,元空间并不在虚拟机内存中而是使用本地内存,但是本地内存也有打满的时候,所以也会有异常。

/**
 * JVM Options: -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
 */
public class MetaspaceOOMDemo {
 
    public static void main(String[] args) {
 
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(MetaspaceOOMDemo.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                //动态代理创建对象
                return methodProxy.invokeSuper(o, objects);
            });
            enhancer.create();
        }
    }
}

借助 Spring 的 GCLib 实现动态创建对象

Exception in thread "main" org.springframework.cglib.core.CodeGenerationException: java.lang.OutOfMemoryError-->Metaspace

方法区溢出也是一种常见的内存溢出异常,在经常运行时生成大量动态类的应用场景中,就应该特别关注这些类的回收情况。这类场景除了上边的 GCLib 字节码增强和动态语言外,常见的还有,大量 JSP 或动态产生 JSP 文件的应用(远古时代的传统软件行业可能会有)、基于 OSGi 的应用(即使同一个类文件,被不同的加载器加载也会视为不同的类)等。

原因分析

  1. 加载过多的类:每个类在加载到JVM时都会占用一定的方法区空间。如果程序加载了大量的类,那么方法区可能会被占满,导致OOM。
  2. 类加载器泄漏:如果类加载器没有正确地释放已经加载的类,那么这些类将一直占用方法区空间,导致方法区溢出。
  3. 动态生成类:在使用诸如JSP、反射或ASM等技术动态生成类时,如果生成过多的类或频繁地生成和卸载类,可能会导致方法区溢出

解决方案

  • 限制方法区大小:通过-XX:MaxMetaspaceSize参数设置方法区的最大值,避免无限制增长。这需要根据应用程序的实际情况进行调整。
  • 检查类加载器实现:确保自定义的类加载器正确实现了资源的释放,避免类加载器泄露。同时,注意检查和升级可能导致泄露的第三方库。
  • 优化类加载策略:按需加载和卸载类,避免不必要的类加载。可以考虑使用模块化技术(如OSGi)来管理类的加载和卸载。

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

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

相关文章

CORDIC Translate

随便记录一下下: Cordic IP核使用说明以及避坑记录-CSDN博客 本次只用到了Translate,记录一下自己遇到的坑坑 实际配置: timescale 1ns / 1nsmodule cordic_tb();reg clk;wire m_axis_dout_tvalid;reg s_axis_cartesian_tvalid 0;wire [31…

三分钟了解什么是消费返利

消费返利作为一种创新的营销手段,不仅增强了消费者的购物体验,还为电商平台及商家带来了更多的用户粘性和复购率。什么是消费返利,其背后的运作机制又是如何的呢? 返利的定义: 返利即是一种消费激励措施,当消费者在指…

网络安全防御 -- 防火墙安全策略用户认证综合实验

实验拓扑: 实验目的: 1、DMZ区内的服务器,办公区仅能在办公时间内(9:00-18:00)可以访问,生产区的设备全天可以访问。 2、生产区不允许访问互联网,办公区和游客区允许访问互联网。 3、办公区设备10.0.2.10不允许访问DM…

ns3-gym入门(一):代码结构和简单例子

ns3-gym真的好难学,网上可以参考的例子也太少了,如果有用这个做路由的麻烦联系我交流一下吧,太痛苦了 一、安装 之前的文章已经提到过了,这里不赘述了 二、运行简单的例子 用两个终端的方式运行感觉更加直观,但是仍然…

白嫖3个域名用cloudeflare托管

这也是看到别的up主分享得到的,我也分享一下给你们。 浏览器打开官网 https://register.us.kg/ 然后注册 根据信息填地址电话可以去另一个网页生成,名字姓名之类的可以填自己喜欢的,注意一下,我尝试了一下谷歌的邮箱&#xff0…

webstorm问题解决:无法识别 @

问题解决tsconfig.json 问题 本地的 vite.config.ts 已经配置 路径 但是,我用webstorm 上识别不了 解决 新增文件tsconfig.json,添加 baseUrl 和 paths 的配置,以告诉 TypeScript 和 WebStorm 如何解析路径别名 tsconfig.json {&quo…

以设备为核心的状态自动采集、人工运维和预测性维护为一体的智能管理系统

中服云设备全生命周期管理系统充分利用物联网、人工智能、机器学习、大数据等新一代技术,实现对企业生产设备从采购、安装、调试、使用、维护、维修、改造、更新直到报废全生命周期的智能化、数字化、可视化的实时管控,支持设备运行状态的自动采集和人工…

SketchUp Pro 2023: 强大的跨平台建模软件

SketchUp Pro 2023 是一款广受建筑设计师、工程师和创意设计师欢迎的专业建模软件,它结合了直观的用户界面和强大的功能,为用户提供了创造、设计和分享他们的想法的理想平台。无论是初学者还是经验丰富的专业人士,SketchUp Pro 2023 都能够满…

JVM是如何管理内存的?图文详解GC垃圾回收算法

前言:在C/C中对于变量的内存空间一般都是由程序员手动进行管理的,往往会伴随着大量的 malloc 和 free 操作,常常会有很多问题困扰开发者,这个代码会不会发生内存泄漏?会不会重复释放内存?但是在Java开发中我…

python作业二

# 二进制转化为十进制 num input("num:")def binaryToDecimal(binaryString):he 0length len(binaryString)for i in range(length):he int(binaryString[i]) * 2 ** (length - i - 1)return heprint(binaryToDecimal(num))代码运行如下: import math…

数据结构4.0——串的定义和基本操作

串的定义(逻辑结构) 串,即字符串(String)是由零个或多个字符组成的有序数列。 一般记为Sa1a2....an(n>0) 其中,S是串名,单引号括起来的字符序列是串的值;ai可以是字母、数字或其他字符;串中字符的个数n称为串的长度。n0时的…

印尼Facebook直播网络需要达到什么要求?

在全球化浪潮的推动下,海外直播正受到企业、个人和机构的广泛关注和青睐。无论是用于营销、推广还是互动,海外直播为各种组织提供了更多机会和可能性。本文将探讨在进行印尼Facebook直播前,需要满足哪些网络条件以确保直播的质量和用户体验。…

Codeforces Round 957 (Div. 3) F. Valuable Cards

题目 #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 #define ll long longconst int maxn 1e6 5, inf 1e18, maxm 4e4 5…

容器docker 架构命令案例

文章目录 前言一、docker1.1 为什么有docker1.2 docker架构1.3 docker 安装1.4 docker中央仓库1.5 docker 基本指令1.6 docker数据卷&#xff0c;挂载例&#xff1a;nginx 数据卷挂载例&#xff1a;mysql 本地持久化 1.7 镜像制作镜像结构dockerfile基础指令容器生成镜像 1.8 d…

如何使用Github Page搭建个人网站【踩坑实录多图预警】

读前提示 教程链接&#xff1a;使用GitHub Page创建个人网站和博客 | GitHub 中文社区 点进网站就是非常详细的步骤介绍&#xff0c;基本按部就班来跟着做就OK了&#xff0c;结果不是很熟悉操作&#xff0c;踩了几个坑还是顺利搞定了。 踩坑后的建议&#xff1a;一定要先完成…

百元不入耳耳机哪款好?强推这五款宝藏产品

如今无线蓝牙耳机是年轻人学习通勤、健身娱乐的标配&#xff0c;但普及率极高的入耳式耳机却存在堵塞耳孔、影响外界感知等不足&#xff0c;而开放式耳机的出现恰好弥补了这些不足&#xff0c;受到了越来越多人的欢迎。但要从各种品牌、各类型号的开放式耳机中选出一款最适合自…

数学建模·灰色关联度

灰色关联分析 基本原理 灰色关联分析可以确定一个系统中哪些因素是主要因素&#xff0c;哪些是次要因素&#xff1b; 灰色关联分析也可以用于综合评价&#xff0c;但是由于数据预处理的方式不同&#xff0c;导致结果 有较大出入 &#xff0c;故一般不采用 具体步骤 数据预处理…

Nginx和Tomcat实现负载均衡群集部署应用

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作时间&…

20240711每日消息队列-------------MQ消息的积压的折磨

目标 解决MQ消息的积压 背景 菜馆系统----------- 系统读取消息&#xff0c;处理业务逻辑&#xff0c;持久化订单和菜品数据&#xff0c;然后将其显示在菜品管理客户端上。 最初我们的用户基数很小&#xff0c;上线后的一段时间内&#xff0c;MQ消息通信还算顺利。 随着用户…

在Mac上一键安装Mysql(解决所有安装问题)

重点强调安装mysql成功的关键在于安装的版本不能是最新&#xff01;&#xff01; 目录 一&#xff1a;下载mysql数据库安装部分到此结束 二&#xff1a;配置mysql数据库三&#xff1a;启动mysql数据库四&#xff1a;各类奇葩问题总结 一&#xff1a;下载mysql数据库 1.进入MyS…