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
英文地址,請注明出處:http://en.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現狀(下)

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…