首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 應用在 Linux 上內存持續增長導致 OOM 的排查思路

     編輯:程式設計綜合問答

現象對比

環境啟動內存運行趨勢結果
Windows (本地)幾十 MB心跳/任務後下降,隨後回升健康
Linux (生產)200+ MB持續上升,不回落,最終 OOM崩潰

核心差異分析

  1. JVM 位數:Windows 可能跑 32 位 JVM(限制 1.5-2GB),Linux 必須用 64 位(-d64),否則大內存無法識別。
  2. Off-Heap 內存:Netty 預設使用 Direct Buffer(-XX:MaxDirectMemorySize),若未顯式設置,默認等於 -Xmx,導致堆外內存無限增長。
  3. GC 行為:Linux 上預設 GC 策略可能不同(如 UseParallelGC vs G1),需顯式指定。
  4. 線程棧大小:-Xss 默認 1MB,200+ 連接 + 定時任務線程 = 數百 MB 棧內存。

排查工具鏈

# 1. 查看進程內存分佈
jcmd  VM.native_memory summary

# 2. 堆內存快照
jmap -dump:live,format=b,file=heap.hprof 
# 用 MAT/Eclipse Memory Analyzer 分析

# 3. 線程快照
jstack  > threads.txt
# 關注 RUNNABLE 狀態的 Netty IO 線程、定時任務線程

# 4. GC 日志(啟動參數加上)
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log

常見洩漏點與修復

1. Netty ByteBuf 未釋放

// 必須在 handler 最後釋放
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    ByteBuf buf = (ByteBuf) msg;
    try {
        // 處理業務
    } finally {
        ReferenceCountUtil.release(buf); // 關鍵!
    }
}

2. 定時任務線程池未關閉

@PreDestroy
public void shutdown() {
    scheduledExecutorService.shutdownNow(); // 春容器關閉時調用
}

3. 啟動參數建議(生產環境)

-server -d64
-Xms2g -Xmx2g
-XX:MaxDirectMemorySize=1g
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/heap.hprof
-Xss512k

總結

Windows/Linux 內存表現不一致,90% 是堆外內存(Direct Buffer / 線程棧 / JNI)未受堆限制導致。優先檢查 Netty 洩漏、線程池配置、JVM 參數是否顯式限制 Off-Heap。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved