动态

详情 返回 返回

面試被問:OOM類型有哪些?怎麼答? - 动态 详情

大家好,我是小富~

面試官:OOM類型有哪些?

你:就是老年代放不下了嘛!

面試官:等消息吧!

OOM(Out Of Memory) 錯誤有多種類型,每種類型對應不同的內存區域或觸發場景。以下是常見的 OOM 類型及其產生原因:


1. java.lang.OutOfMemoryError: Java heap space

  • 觸發原因:堆內存(存放對象實例)不足,無法分配新對象。
  • 典型場景

    • 內存泄漏:對象被無意長期引用(如靜態集合、未關閉的資源),無法被 GC 回收。
    • 堆大小不足:JVM 堆參數(-Xmx)設置過小,或程序需要處理的數據量超出預期。
    • 大對象分配:一次性申請超大對象(如大數組)。

示例

// 不斷向集合中添加對象導致堆溢出
List<Object> list = new ArrayList<>();
while (true) {
    list.add(new Object());
}

解決方案

  • 檢查內存泄漏(使用 jmap + MAT 分析堆轉儲)。
  • 調整堆大小(-Xmx-Xms)。
  • 優化代碼邏輯,減少對象生命週期。

2. java.lang.OutOfMemoryError: Metaspace(Java 8+)或 PermGen space(Java 7-)

  • 觸發原因:元空間(Metaspace)或永久代(PermGen)內存不足,用於存儲類元數據、方法信息等。
  • 典型場景

    • 動態生成大量類(如使用 CGLib、反射、動態代理)。
    • 類加載器未正確釋放(如頻繁部署的 Web 應用導致舊類未卸載)。

示例

// 使用 CGLib 動態生成大量代理類
Enhancer enhancer = new Enhancer();
while (true) {
    enhancer.setSuperclass(OOM.class);
    enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args)));
    enhancer.create();
}

解決方案

  • 調整元空間大小(-XX:MaxMetaspaceSize)。
  • 檢查類加載器泄漏或動態類生成邏輯。

3. java.lang.OutOfMemoryError: Direct buffer memory

  • 觸發原因:直接內存(Direct Memory,通過 ByteBuffer.allocateDirect() 分配)耗盡。
  • 典型場景

    • 頻繁申請直接內存但未及時釋放(需依賴 System.gc()Cleaner 機制)。
    • JVM 直接內存參數(-XX:MaxDirectMemorySize)設置過小。

示例

// 不斷申請直接內存
List<ByteBuffer> buffers = new ArrayList<>();
while (true) {
    buffers.add(ByteBuffer.allocateDirect(1024 * 1024)); // 1MB
}

解決方案

  • 檢查直接內存使用代碼,確保及時釋放。
  • 調整 -XX:MaxDirectMemorySize

4. java.lang.OutOfMemoryError: Unable to create new native thread

  • 觸發原因:操作系統限制線程數量,無法創建新線程。
  • 典型場景

    • 線程數超過系統限制(如 Linux 的 ulimit -u)。
    • 每個線程的棧內存(-Xss)設置過大,導致總內存佔用超出。

示例

// 無限創建線程
while (true) {
    new Thread(() -> {
        try { Thread.sleep(1000000); } catch (InterruptedException e) {}
    }).start();
}

解決方案

  • 減少線程數(使用線程池)。
  • 調整 -Xss 減小線程棧大小。
  • 修改系統線程數限制。

5. java.lang.OutOfMemoryError: Requested array size exceeds VM limit

  • 觸發原因:嘗試分配超過 JVM 限制的數組(通常接近 Integer.MAX_VALUE)。
  • 典型場景:錯誤計算數組長度,如 new int[Integer.MAX_VALUE]

解決方案

  • 檢查數組長度計算邏輯,使用合理的數據結構。

6. java.lang.OutOfMemoryError: GC Overhead limit exceeded

  • 觸發原因:GC 頻繁執行但回收效率極低(如 98% 時間用於 GC,僅回收 2% 內存)。
  • 典型場景:堆內存幾乎被佔滿,且存在大量無法回收的對象(內存泄漏)。

解決方案

  • 檢查內存泄漏或優化 GC 策略(如調整堆大小、更換垃圾回收器)。

7. java.lang.OutOfMemoryError: CodeCache(JIT 編譯代碼緩存溢出)

  • 觸發原因:JIT 編譯器生成的本地代碼佔滿代碼緩存區。
  • 典型場景:高頻動態編譯大量方法(如複雜的熱點代碼)。

解決方案

  • 調整代碼緩存大小(-XX:ReservedCodeCacheSize)。
  • 關閉分層編譯(-XX:-TieredCompilation)。

總結

OOM 的根本原因是 JVM 內存區域不足資源耗盡,需結合錯誤類型分析具體內存區域(堆、元空間、直接內存等)。

排查時可通過以下步驟:

1、確定 OOM 類型(通過錯誤日誌)。

2、使用工具分析(如 jstatjmapVisualVMMAT)。

3、調整 JVM 參數或優化代碼邏輯。

等被裁員在學習?趕緊的吧!

user avatar jianxiangjie3rkv9 头像 seazhan 头像 zzger 头像 kohler21 头像 zzzzbw 头像 aipaobudezuoyeben 头像 coderdd 头像 shouke 头像 huangxunhui 头像 emanjusaka 头像 chuck1sn 头像 javaedge 头像
点赞 52 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.