欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java內(nèi)存溢出常見(jiàn)原因及解決過(guò)程

 更新時(shí)間:2025年07月18日 16:29:50   作者:alden_ygq  
Java內(nèi)存溢出分為堆、Metaspace、棧、直接內(nèi)存及本地內(nèi)存,由對(duì)象過(guò)多、泄漏、遞歸過(guò)深、NIO使用不當(dāng)?shù)纫l(fā),解決方法包括調(diào)整參數(shù)、優(yōu)化代碼、使用MAT分析,及監(jiān)控預(yù)警,關(guān)鍵在分析與調(diào)優(yōu)結(jié)合

以下是 Java 內(nèi)存溢出(OOM)的常見(jiàn)原因及對(duì)應(yīng)的解決方法,結(jié)合實(shí)戰(zhàn)案例和代碼示例說(shuō)明:

一、堆內(nèi)存溢出(Java heap space)

1. 常見(jiàn)原因

  • 對(duì)象創(chuàng)建過(guò)多:循環(huán)中不斷創(chuàng)建新對(duì)象,導(dǎo)致堆內(nèi)存耗盡。
  • 內(nèi)存泄漏:對(duì)象無(wú)法被 GC 回收(如靜態(tài)集合持有對(duì)象引用、資源未關(guān)閉)。
  • 大對(duì)象分配:數(shù)組、集合等占用內(nèi)存過(guò)大,超過(guò)堆空間限制。

2. 示例代碼(觸發(fā)堆溢出)

import java.util.ArrayList;
import java.util.List;

public class HeapOOM {
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        while (true) {
            // 每次創(chuàng)建1MB對(duì)象
            list.add(new byte[1024 * 1024]); 
        }
    }
}

3. 解決方法

增加堆內(nèi)存

java -Xms2g -Xmx2g -jar app.jar  # 初始和最大堆均為2GB

優(yōu)化對(duì)象生命周期

  • 避免在循環(huán)中創(chuàng)建大對(duì)象。
  • 使用對(duì)象池(如 Apache Commons Pool)重用對(duì)象。

排查內(nèi)存泄漏

  • 通過(guò) MAT(Memory Analyzer Tool)分析堆轉(zhuǎn)儲(chǔ)文件,找出泄漏點(diǎn)。
  • 檢查靜態(tài)集合(如static List)是否持有對(duì)象引用。

二、Metaspace 溢出(Metaspace)

1. 常見(jiàn)原因

  • 動(dòng)態(tài)生成類過(guò)多:如大量使用反射、CGLIB 代理、字節(jié)碼框架(如 ASM)。
  • 類加載器未釋放:自定義類加載器加載的類無(wú)法被卸載。
  • Metaspace 空間設(shè)置過(guò)小:默認(rèn)無(wú)上限,但可能受系統(tǒng)內(nèi)存限制。

2. 示例代碼(觸發(fā) Metaspace 溢出)

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

public class MetaspaceOOM {
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Object.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> proxy.invokeSuper(obj, args1));
            enhancer.create();  // 動(dòng)態(tài)生成代理類
        }
    }
}

3. 解決方法

增加 Metaspace 大小

java -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -jar app.jar

避免重復(fù)生成類

  • 緩存動(dòng)態(tài)生成的類(如 Hibernate 的BytecodeProvider)。
  • 減少反射調(diào)用頻率。

排查類加載器泄漏

  • 確保自定義類加載器正確釋放資源。
  • 使用jstat -class <pid>監(jiān)控類加載數(shù)量。

三、棧溢出(StackOverflowError)

1. 常見(jiàn)原因

  • 遞歸過(guò)深:方法調(diào)用鏈過(guò)長(zhǎng)(如無(wú)終止條件的遞歸)。
  • ??臻g設(shè)置過(guò)小:默認(rèn)棧空間(如 Linux 下為 1MB)無(wú)法滿足復(fù)雜調(diào)用。

2. 示例代碼(觸發(fā)棧溢出)

public class StackOverflow {
    public static void main(String[] args) {
        recursiveCall();
    }

    private static void recursiveCall() {
        recursiveCall();  // 無(wú)限遞歸
    }
}

3. 解決方法

增加棧空間

java -Xss2m -jar app.jar  # ??臻g設(shè)置為2MB

優(yōu)化遞歸邏輯

  • 將遞歸改為迭代(如使用棧數(shù)據(jù)結(jié)構(gòu)模擬遞歸)。
  • 添加終止條件,避免無(wú)限遞歸。

排查內(nèi)存占用大的局部變量

  • 減少方法中大型數(shù)組或?qū)ο蟮氖褂谩?/li>

四、直接內(nèi)存溢出(Direct buffer memory)

1. 常見(jiàn)原因

  • NIO 直接內(nèi)存使用過(guò)多ByteBuffer.allocateDirect()分配的內(nèi)存超出限制。
  • 未釋放直接內(nèi)存DirectByteBuffer對(duì)象被 GC 回收,但物理內(nèi)存未釋放。
  • 直接內(nèi)存上限設(shè)置過(guò)小:默認(rèn)與堆內(nèi)存相同(-Xmx)。

2. 示例代碼(觸發(fā)直接內(nèi)存溢出)

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class DirectMemoryOOM {
    public static void main(String[] args) {
        List<ByteBuffer> buffers = new ArrayList<>();
        while (true) {
            // 每次分配100MB直接內(nèi)存
            ByteBuffer buffer = ByteBuffer.allocateDirect(100 * 1024 * 1024);
            buffers.add(buffer);
        }
    }
}

3. 解決方法

限制直接內(nèi)存大小

java -XX:MaxDirectMemorySize=512m -jar app.jar

手動(dòng)釋放直接內(nèi)存

import sun.misc.Cleaner;
import java.nio.ByteBuffer;

public class DirectMemoryRelease {
    public static void release(ByteBuffer buffer) {
        if (buffer.isDirect()) {
            Cleaner cleaner = ((sun.nio.ch.DirectBuffer) buffer).cleaner();
            if (cleaner != null) {
                cleaner.clean();  // 手動(dòng)釋放直接內(nèi)存
            }
        }
    }
}

使用內(nèi)存池

  • 采用 Netty 的PooledByteBufAllocator管理直接內(nèi)存。

五、本地內(nèi)存Native Memory

1. 內(nèi)存溢出類型

java.lang.OutOfMemoryError: unable to create new native thread  // 線程創(chuàng)建失敗
java.lang.OutOfMemoryError: Compressed class space  // 壓縮類空間溢出

2. 核心原因

JNI 本地庫(kù)內(nèi)存泄漏

  • Java 通過(guò) JNI 調(diào)用 C/C++ 代碼時(shí),本地庫(kù)未正確釋放內(nèi)存。

堆外內(nèi)存分配過(guò)多

  • 例如 Netty、MappedByteBuffer 等框架直接操作堆外內(nèi)存,超出系統(tǒng)限制。

壓縮類空間不足

  • JDK 8+ 將類元數(shù)據(jù)分為Klass MetaspaceCompressed Class Space,后者默認(rèn) 1GB。

3. 解決方法

# 增加壓縮類空間
java -XX:CompressedClassSpaceSize=256m -jar app.jar

# 使用內(nèi)存分析工具(如Native Memory Tracking)
java -XX:NativeMemoryTracking=detail -XX:+PrintNMTStatistics -jar app.jar

五、內(nèi)存溢出排查工具與步驟

生成堆轉(zhuǎn)儲(chǔ)文件

# 手動(dòng)觸發(fā)
jmap -dump:format=b,file=heapdump.hprof <pid>

# 自動(dòng)觸發(fā)(推薦)
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump.hprof -jar app.jar

分析工具

  • MAT(Memory Analyzer Tool)

分析堆轉(zhuǎn)儲(chǔ)文件,定位大對(duì)象和內(nèi)存泄漏(如 “Leak Suspects” 報(bào)告)。

  • VisualVM

實(shí)時(shí)監(jiān)控內(nèi)存、線程、GC 情況,支持堆轉(zhuǎn)儲(chǔ)分析。

  • GC 日志分析
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/data/gc.log -jar app.jar

排查步驟

  • 確認(rèn) OOM 類型(堆、Metaspace、棧、直接內(nèi)存)。
  • 分析堆轉(zhuǎn)儲(chǔ)文件,找出占用內(nèi)存最大的對(duì)象。
  • 檢查對(duì)象引用鏈,確定是否存在內(nèi)存泄漏。
  • 優(yōu)化代碼或調(diào)整 JVM 參數(shù)。

六、預(yù)防措施

合理設(shè)置 JVM 參數(shù)

java -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
     -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump.hprof \
     -jar app.jar

資源管理最佳實(shí)踐

  • 使用try-with-resources確保資源關(guān)閉。
  • 避免靜態(tài)集合持有長(zhǎng)生命周期對(duì)象。

監(jiān)控與預(yù)警

  • 通過(guò) Prometheus+Grafana 監(jiān)控 JVM 指標(biāo)(如堆使用率、GC 頻率)。
  • 設(shè)置告警閾值(如堆使用率超過(guò) 80% 時(shí)觸發(fā)通知)。

七、典型案例分析

案例 1:某電商系統(tǒng)高峰期頻繁 Full GC

原因

  • 緩存大量商品信息,導(dǎo)致老年代空間不足。

解決

  • 增加堆內(nèi)存至 8GB(-Xmx8g)。
  • 優(yōu)化緩存策略,設(shè)置合理過(guò)期時(shí)間。
  • 改用 G1 收集器(-XX:+UseG1GC)。

案例 2:某微服務(wù)框架啟動(dòng)慢且 OOM

原因

  • Spring 框架動(dòng)態(tài)生成大量代理類,Metaspace 不足。

解決

  • 設(shè)置-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g
  • 升級(jí) Spring 版本,優(yōu)化類加載機(jī)制。

通過(guò)以上方法,可系統(tǒng)性解決 Java 內(nèi)存溢出問(wèn)題。關(guān)鍵在于監(jiān)控分析、代碼優(yōu)化、參數(shù)調(diào)優(yōu)三者結(jié)合,同時(shí)建立完善的預(yù)警機(jī)制。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java斗地主發(fā)牌課程設(shè)計(jì)

    Java斗地主發(fā)牌課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了Java斗地主發(fā)牌課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Spring Boot集成 Spring Boot Admin 監(jiān)控

    Spring Boot集成 Spring Boot Admin 監(jiān)控

    這篇文章主要介紹了Spring Boot集成 Spring Boot Admin 監(jiān)控,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞的實(shí)現(xiàn)詳解

    SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞的實(shí)現(xiàn)詳解

    這篇文章主要介紹了SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞,對(duì)于重定向,可以通過(guò)FlashMap或RedirectAttributes來(lái)在請(qǐng)求間傳遞數(shù)據(jù),因?yàn)橹囟ㄏ蛏婕皟蓚€(gè)獨(dú)立的HTTP請(qǐng)求,而轉(zhuǎn)發(fā)則在同一請(qǐng)求內(nèi)進(jìn)行,數(shù)據(jù)可以直接通過(guò)HttpServletRequest共享,需要的朋友可以參考下
    2022-07-07
  • Spring?Boot?中的?@DateTimeFormat?和?@JsonFormat?的用法及作用詳解

    Spring?Boot?中的?@DateTimeFormat?和?@JsonFormat?的用法及作用詳解

    本文介紹了SpringBoot中的@DateTimeFormat和@JsonFormat注解的用法,解釋了它們?cè)谔幚砣掌诤蜁r(shí)間數(shù)據(jù)時(shí)的作用,并通過(guò)實(shí)例代碼展示了如何在REST控制器中使用這些注解,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • 如何在SpringBoot項(xiàng)目中使用Oracle11g數(shù)據(jù)庫(kù)

    如何在SpringBoot項(xiàng)目中使用Oracle11g數(shù)據(jù)庫(kù)

    這篇文章主要介紹了在SpringBoot項(xiàng)目中使用Oracle11g數(shù)據(jù)庫(kù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java?NIO通信基礎(chǔ)示例詳解

    Java?NIO通信基礎(chǔ)示例詳解

    這篇文章主要為大家介紹了Java?NIO通信基礎(chǔ)使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • eclipse 中的javac命令與java命令

    eclipse 中的javac命令與java命令

    這篇文章主要介紹了eclipse javac命令與java命令的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • springboot打包無(wú)法讀取yml、properties等配置文件的解決

    springboot打包無(wú)法讀取yml、properties等配置文件的解決

    這篇文章主要介紹了springboot打包無(wú)法讀取yml、properties等配置文件的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • IDEA安裝后找不到.vmoptions文件的問(wèn)題及解決

    IDEA安裝后找不到.vmoptions文件的問(wèn)題及解決

    這篇文章主要介紹了IDEA安裝后找不到.vmoptions文件的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • SpringBoot?分模塊開(kāi)發(fā)的操作方法

    SpringBoot?分模塊開(kāi)發(fā)的操作方法

    這篇文章主要介紹了SpringBoot?分模塊開(kāi)發(fā)的操作方法,通過(guò)在原項(xiàng)目新增一個(gè)maven模塊,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04

最新評(píng)論