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

Java Direct Buffer Memory溢出:Tomcat APR模式下的排查與解決

     編輯:程式設計綜合問答

異常`OutOfMemoryError: Direct buffer memory`出現在Tomcat使用APR/native庫時,表明堆外內存(Direct Memory)耗盡,而非堆內存。本文深度解析原因與解決方案。

異常堆棧關鍵信息


java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory
at java.nio.DirectByteBuffer.
at org.apache.coyote.http11.InternalAprInputBuffer.
at org.apache.coyote.http11.Http11AprProcessor.
  • 發生在`Http11AprProcessor`創建時,每個連接處理器分配`DirectByteBuffer`用於APR網絡讀寫。
  • APR模式下,Tomcat默認使用堆外內存作為Socket讀寫緩衝區,避免JNI拷貝開銷。

核心原因

  1. 并發連接數過大:每個連接佔用固定Direct Buffer(默認8KB-16KB),高併發下總量超限。
  2. MaxDirectMemorySize默認值小:JDK默認與最大堆內存(-Xmx)相同,若-Xmx較小或未顯式設置,Direct Memory極易耗盡。
  3. APR/native庫版本問題:舊版本可能存在內存洩漏或釋放不及時。
  4. 連接處理器未及時回收:keep-alive連接長佔用緩衝區,或處理邏輯阻塞導致釋放延遲。

解決方案(按推薦順序)

1. 顯式設置Direct Memory上限(最直接)

在Tomcat啟動腳本(`catalina.sh`/`setenv.sh`)中添加:

CATALINA_OPTS="-XX:MaxDirectMemorySize=512m"  # 根據機器內存調整,建議≥1GB

或JVM參數:`-XX:MaxDirectMemorySize=1g`

2. 調整Tomcat連接器參數




           ...
/>

3. 考慮切換NIO2協議(非APR)

若不依賴APR的高性能優勢(如OpenSSL硬件加速),改用`Http11Nio2Protocol`:



NIO2使用堆內ByteBuffer(受`-Xmx`控制),避開Direct Memory限制,現代JDK性能已接近APR。

4. 排查應用層Direct Buffer使用

  • Netty、RocketMQ、HBase等組件可能大量分配Direct Buffer,需統一規劃總上限。
  • 使用`-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xlog:gc+ref=debug`監控Direct Buffer GC情況。

驗證與監控

  • 啟動後`jcmd VM.native_memory summary`查看Direct Memory佔用。
  • VisualVM/JConsole監控`Non-Heap Memory` → `Direct Buffer`趨勢。
  • 壓測驗證併發連接數下內存增長曲線。
關鍵認知:Direct Memory不受-Xmx控制,必須顯式設置-XX:MaxDirectMemorySize,APR模式下更是剛需。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved