【面試場景題】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
英文地址,請注明出處:http://en.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;直接上代碼 ②代碼模塊拆解與詳細解…