【面试场景题】spring应用启动时出现内存溢出怎么排查

文章目录

      • 一、定位 OOM 类型
      • 二、基础排查:调整 JVM 参数与日志
      • 三、堆内存溢出(Heap Space)排查
        • 1. 分析堆转储文件
        • 2. 典型场景与解决
      • 四、元空间溢出(Metaspace)排查
        • 1. 分析类加载情况
        • 2. 典型场景与解决
      • 五、直接内存溢出(Direct Buffer)排查
        • 1. 定位直接内存使用者
        • 2. 典型场景与解决
      • 六、栈溢出(StackOverflowError)排查
      • 七、总结:排查流程梳理

Spring 应用启动时出现内存溢出(OOM)是常见问题,通常与 初始化资源过多配置不当代码缺陷 有关。排查需结合 JVM 内存模型、Spring 启动流程及工具分析,步骤如下:

一、定位 OOM 类型

首先通过错误日志确定 OOM 的具体类型,不同区域的溢出对应不同问题:

  1. java.lang.OutOfMemoryError: Java heap space
  • 堆内存不足:Spring 启动时创建大量对象(如 Bean、缓存数据、初始化集合)超出堆容量。
  1. java.lang.OutOfMemoryError: Metaspace
  • 元空间不足:加载的类过多(如大量动态生成类、依赖包过大),超出元空间限制。
  1. java.lang.OutOfMemoryError: Direct buffer memory
  • 直接内存不足:NIO 直接内存分配过多(如 Netty 缓冲区、文件 IO 缓存)。
  1. java.lang.StackOverflowError
  • 栈内存溢出:Spring 启动时方法调用栈过深(如递归依赖、循环依赖处理不当)。

二、基础排查:调整 JVM 参数与日志

  1. 临时调大内存参数
    先尝试增加内存排查是否因配置不足导致,启动时添加 JVM 参数:
# 堆内存(初始=最大,避免动态扩容)
-Xms2g -Xmx2g 
# 元空间(根据依赖规模调整)
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m 
# 直接内存(若怀疑直接内存问题)
-XX:MaxDirectMemorySize=1g 

若调大后启动成功,说明原配置不足,需根据实际需求优化参数。

  1. 开启 OOM 日志与堆转储

添加参数记录关键信息,便于后续分析:

# OOM 时自动生成堆转储文件(路径自定义)
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/spring-oom.hprof
# 打印 GC 详细日志(观察内存增长趋势)
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/spring-gc.log

三、堆内存溢出(Heap Space)排查

Spring 启动时堆溢出多因 初始化大量 Bean加载大数据(如缓存预热、配置解析)。

1. 分析堆转储文件

使用工具分析 spring-oom.hprof 堆转储文件,定位大对象或异常对象:

  • 工具:Eclipse MAT(Memory Analyzer Tool)、JProfiler、VisualVM。
  • 关键步骤
  1. 打开堆转储文件,查看 Dominator Tree(支配树),找出占用内存最多的对象。
  2. 检查是否有 异常大的集合(如 HashMapList),可能是初始化时加载了过多数据。
  3. 查看 Spring Bean 实例:是否有不必要的单例 Bean 被大量创建,或 Bean 本身持有大对象(如缓存全量数据)。
2. 典型场景与解决
  • 场景 1:Bean 数量过多
    若项目依赖过多(如引入大量 Starter),Spring 会扫描并创建大量 Bean(尤其是 @ComponentScan 范围过大)。
    解决:缩小扫描范围(@ComponentScan(basePackages = "com.xxx.core")),排除不需要的自动配置(@SpringBootApplication(exclude = XXXAutoConfiguration.class))。

  • 场景 2:初始化时加载全量数据
    @PostConstruct 方法中加载全表数据到内存(如 List<User> allUsers = userMapper.selectAll())。
    解决:按需加载(分页/懒加载),或延迟初始化(非启动时加载)。

  • 场景 3:循环依赖导致的对象膨胀
    虽然 Spring 支持循环依赖,但复杂循环可能导致对象初始化时持有大量引用,间接占用内存。
    解决:通过 @Lazy 延迟注入,或重构代码消除循环依赖。

四、元空间溢出(Metaspace)排查

元空间存储类信息(类结构、方法、注解等),溢出通常因 加载类过多类未被卸载

1. 分析类加载情况
  • 查看类加载数量:启动时添加参数 -XX:+TraceClassLoading -XX:+TraceClassUnloading,日志中记录所有加载/卸载的类,排查是否有异常类(如动态生成的代理类、重复加载的类)。
  • 工具分析:用 jmap -clstats <pid> 查看类加载统计,重点关注:
  • 类总数是否过大(如超过 10 万)。
  • 是否有大量动态代理类(如 CGLIB 代理,每个代理生成一个新类)。
  • 是否有重复类加载(同一类被不同类加载器加载)。
2. 典型场景与解决
  • 场景 1:依赖包过多/过大
    如引入大量第三方库(如全量 Spring Cloud 组件),每个 Jar 包含大量类。
    解决:剔除无用依赖(用 mvn dependency:analyze 检测),使用瘦身插件(如 Spring Boot 的 spring-boot-maven-plugin 排除冗余依赖)。

  • 场景 2:动态代理类泛滥
    Spring AOP 中,@Transactional@Async 等注解会通过 CGLIB/JDK 生成代理类,若代理目标过多(如每个 Service 都被代理),会产生大量类。
    解决:缩小 AOP 切点范围(@Pointcut("execution(* com.xxx.service.*Service.*(..))")),避免对无必要的类代理。

  • 场景 3:类加载器泄漏
    自定义类加载器未被回收(如热部署工具、插件化框架),导致加载的类长期占用元空间。
    解决:确保类加载器使用后被正确释放,避免静态引用持有类加载器。

五、直接内存溢出(Direct Buffer)排查

直接内存由 JVM 外部管理(如 NIO 的 DirectByteBuffer),溢出常见于 网络/IO 密集型应用

1. 定位直接内存使用者
  • 日志分析:添加 JVM 参数 -XX:TraceDirectMemoryAllocation 跟踪直接内存分配,日志会显示分配位置(如 sun.nio.ch.DirectBuffer.<init>)。
  • 代码排查:检查是否有大量 ByteBuffer.allocateDirect() 调用,且未及时释放(直接内存不受 GC 自动管理,需手动调用 Cleaner.clean() 或等待 GC 触发清理)。
2. 典型场景与解决
  • 场景 1:Netty 等框架的缓冲区配置过大
    如 Netty 服务器设置 ChannelOption.SO_RCVBUF 过大,或 ByteBuf 未释放。
    解决:合理设置缓冲区大小,使用 ReferenceCountUtil.release(buf) 手动释放,或启用 Netty 的泄漏检测(-Dio.netty.leakDetectionLevel=PARANOID)。

  • 场景 2:文件 IO 频繁使用直接内存
    如读取大文件时用 FileChannel.map()(默认使用直接内存)加载全文件。
    解决:分片读取,避免一次性映射大文件。

六、栈溢出(StackOverflowError)排查

栈溢出通常因 方法调用链过深,Spring 启动时常见于:

  1. 循环依赖处理不当
    虽然 Spring 能解决循环依赖,但复杂嵌套(如 A→B→C→A)可能导致初始化时方法调用栈过深。
    解决:用 @Lazy 延迟注入,或重构为接口依赖。

  2. 自定义 BeanPostProcessor 逻辑递归
    BeanPostProcessorpostProcessBeforeInitialization 中调用了被代理的方法,可能触发递归调用。
    解决:避免在处理器中调用目标 Bean 的方法,或通过原生对象(AopContext.currentProxy())调用。

  3. 复杂的 SpEL 表达式解析
    启动时解析嵌套过深的 SpEL 表达式(如 @Value("#{...}") 中多层函数调用)可能导致栈溢出。
    解决:简化 SpEL 表达式,或改为代码中初始化。

七、总结:排查流程梳理

  1. 查看错误日志:确定 OOM 类型(堆/元空间/直接内存)。
  2. 调整参数验证:临时调大对应内存区域,判断是否因配置不足。
  3. 生成并分析堆转储:用 MAT 等工具定位大对象、异常类或资源泄漏。
  4. 结合 Spring 特性排查:聚焦 Bean 初始化、类扫描、AOP 代理等环节。
  5. 优化与验证:减少不必要的对象/类加载,调整初始化逻辑,重新测试。

通过以上步骤,可逐步定位 Spring 启动时 OOM 的根因,最终从配置优化、代码重构或依赖管理等方面解决问题。

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

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

相关文章

2025年经济学专业女生必考证书指南:打造差异化竞争力

在数字经济快速发展的2025年&#xff0c;经济学专业女生面临着诸多机遇与挑战。单纯的理论知识已经难以满足职场需求&#xff0c;企业更看重解决实际问题的能力&#xff0c;特别是将数据转化为商业洞察的专业技能。各类专业资质认证可以成为系统提升能力的途径之一&#xff0c;…

【CAN通信】AUTOSAR架构下TC3xx芯片是如何将一帧CAN报文接收上来的

目录 前言 正文 1.背景介绍 2.CAN报文硬件原理 3.CAN接收软件实现 3.1. vCan_30_Mcan_Interrupt 3.2. vCan_30_Mcan_RxInterrupt 3.3. vCan_30_Mcan_RxBasicCanHandling 4.总结 前言 在《【CAN通信】AUTOSAR架构下TC3xx芯片是如何将一帧CAN报文发送出去的》一文中我们…

STM32H750 RTC介绍及应用

第十一章 RTC介绍及应用 1. RTC 简介 RTC&#xff08;Real-Time Clock&#xff0c;实时时钟&#xff09;是 STM32H750VBT6 中用于提供日历和时钟功能的低功耗外设&#xff0c;即使主电源关闭&#xff0c;只要 VBAT&#xff08;备份电源&#xff09;供电&#xff0c;RTC 仍能持续…

飞网自适应通信:IPv4 与 IPv6 环境下的高效互联

一、网络连接的难题与飞网的解决方案 在日常生活中&#xff0c;我们常常会碰到这样的场景&#xff1a;在家用手机访问公司电脑里的重要文件&#xff0c;或者远程连接家里的NAS设备查看照片和视频。这些操作都需要设备之间建立起安全又稳定的连接。然而&#xff0c;现实中的网络…

拉格朗日多项式

最近打的几个比赛没意思&#xff0c;不是不会就是不会。不过比赛完后看到别人的WP&#xff0c;感觉受益匪浅。先看一个多项式&#xff1a;当输入Xi时会得到一个Si,要求输入一定数量的xi 来求[c] 当可以输入的x个数与c的个数相同时&#xff0c;可以用矩阵直接求解。&#xff08;…

Vue3 + TypeScript 实现文件拖拽上传

应用效果&#xff1a;实例代码&#xff1a;CommonApplyBasicInfoForm.vue<script setup lang"ts" name"CommonApplyBasicInfoForm"> ...... // 选择文件列表 const selectedFiles ref<FileList | null>(null); // 通过 FormData 对象实现文件…

2025全国大学生数学建模C题保姆级思路模型(持续更新):NIPT 的时点选择与胎儿的异常判定

2025全国大学生数学建模C题保姆级思路模型&#xff08;持续更新&#xff09;&#xff1a;NIPT 的时点选择与胎儿的异常判定&#xff0c;完整持续更新内容见文末名片 胎儿遗传信息检测与临床决策数学建模分析讲义 问题一&#xff1a;Y染色体浓度的影响因素探索——线性回归的“侦…

【笔记】Software Engineering at Google

聚焦核心原则&#xff0c;挑取最让我眼前一亮的实践点&#xff0c;特别是那些能直接启发或解决我当前工作中痛点的部分。0. 序言 最近集中精力速读了关于 ​Google 软件工程实践​ 的诸多资料&#xff08;包括官方出版物、工程博客、技术演讲以及社区讨论&#xff09;。面对 G…

无人机防风技术难点解析

防风防御模块的技术难点主要体现在以下几个方面风场感知与精准建模1.复杂风场的实时感知&#xff1a;风&#xff0c;尤其是近地面的风&#xff0c;常常是无规则、瞬息万变的阵风、湍流或风切变。无人机需要通过各种传感器&#xff08;如空速计、惯性测量单元&#xff08;IMU&am…

HarmonyOS 应用开发深度解析:ArkTS 声明式 UI 与精细化状态管理

好的&#xff0c;请看这篇关于 HarmonyOS 应用开发中声明式 UI 状态管理的技术文章。 HarmonyOS 应用开发深度解析&#xff1a;ArkTS 声明式 UI 与精细化状态管理 引言 随着 HarmonyOS 4、5 的广泛应用和 HarmonyOS NEXT 的发布&#xff0c;基于 API 12 及以上的应用开发已成为…

机器学习入门,第一个MCP示例

前面我们已经搭建了属于自己的AI大模型&#xff1a;详情见 https://blog.csdn.net/hl_java/article/details/150591424?spm1001.2014.3001.5501 近期MCP概念这么火&#xff0c;那么它到底是什么呢&#xff0c;借一个例子为你讲解 第一步&#xff1a;理解MCP的核心价值 MCP (Mo…

flutter 中间组件自适应宽度

使用Flexible IntrinsicWidth Row(children: [Text(第一个text),IntrinsicWidth(child: ConstrainedBox(constraints: BoxConstraints(maxWidth: 200), // 最大宽度限制child: Text(中间的text可能很长也可能很短,overflow: TextOverflow.ellipsis,maxLines: 1,),),),Text(第三…

TDengine 时间函数 DAYOFWEEK 用户手册

DAYOFWEEK 函数使用手册 函数描述 DAYOFWEEK 函数用于返回指定日期是一周中的第几天。该函数遵循标准的星期编号约定&#xff0c;返回值范围为 1-7&#xff0c;其中&#xff1a; 1 星期日 (Sunday)2 星期一 (Monday)3 星期二 (Tuesday)4 星期三 (Wednesday)5 星期四 (T…

【STM32】贪吃蛇 [阶段 3] 增强模块结构(架构优化)

这篇博客是 承接&#xff1a;【项目思维】贪吃蛇&#xff08;嵌入式进阶方向&#xff09;中 聚焦于 &#x1f9f1; 阶段 3&#xff1a;增强模块结构&#xff08;架构优化&#xff09; 中的 菜单系统&#xff08;Menu System&#xff09;&#xff0c;这部分的结构优化可以学到的…

江协科技STM32学习笔记补充之004

STM32 ISP 一键下载电路&#xff08;按功能、逻辑与时序拆解&#xff09;

数据库小册(1)

1. 关系型数据库主要考点关系型数据库&#xff1a;架构索引锁语法理论规范2. 如何设计一个关系型数据库设计即模块划分。数据库最主要的功能是存储我们的数据&#xff0c;所以需要一个存储的文件系统。我们要把涉及到的物流数据提供逻辑的形式给组织和表示出来&#xff0c;这是…

记录收入最高的一次私活 选号网,需要大量卖号的人可能需要,比如游戏脚本批量跑的号

选号网管理后台(上传游戏信息、账号信息、 查看记录) http://124.223.214.5:180/admin1 选号网客户端(PC/H5页面 给客户筛选商品用) http://124.223.214.5:181/ 该在线地址仅供低频率测试&#xff0c;正式使用需要另外部署。 功能不满足可以联系开发者定制 一、项目的由来 …

热烈庆祝“中国抗战胜利80周年”,织信低代码助力国之重器砥砺前行!

“从保家卫国到科技强军&#xff0c;织信低代码平台为军工企业数字化转型注入新动能。”80年后的今天&#xff0c;国人记忆从未褪色。2025年9月3日&#xff0c;正值中国抗战胜利80周年阅兵之际&#xff0c;我国国防军工力量在经历长期的艰苦奋斗后&#xff0c;现今终于迎来了曙…

PostgreSQL与SQL Server:B树索引差异及去重的优势

PostgreSQL与SQL Server&#xff1a;B树索引差异及去重的优势 在优化查询性能方面&#xff0c;索引是数据库工程师可使用的最强大工具之一。PostgreSQL和Microsoft SQL Server&#xff08;或Azure SQL&#xff09;都将B树索引用作其默认索引结构&#xff0c;但每个系统实现、维…

【微实验】使用MATLAB制作一张赛博古琴?

当一个理工音乐人没钱去买古琴&#xff0c;我直接用代码画一个古琴&#xff01;目录 零、总脚本&#xff1a; 一、核心功能&#xff1a;交互模块拆解 二、核心价值 一、初始化脚本&#xff1a;参数配置与启动界面 ①废话不说&#xff0c;直接上代码 ②代码模块拆解与详细解…