← Debugging Guides

阅读中文版本

Java — OutOfMemoryError: Direct buffer memory

Diagnose direct buffer exhaustion by tracking native memory use and MaxDirectMemorySize, not only the heap.

advanceddebuggingjavamemory

Symptoms

  • java.lang.OutOfMemoryError: Direct buffer memory
  • Heap usage looks fine while the process grows in native memory
  • The error appears under high network or file IO
  • Only some services on the host are affected

Possible causes

  • Direct ByteBuffers are allocated faster than they are freed by the garbage collector
  • Application code allocates direct buffers without releasing references
  • A framework or Netty allocates pooled direct memory that grows under load
  • The direct memory limit is too low for the workload

Diagnosis steps

Check direct memory tracking

java -XX:MaxDirectMemorySize=256m -XX:+PrintNMTStatistics -jar app.jar

Interpretation

Native Memory Tracking reports direct memory usage, showing whether it approaches the limit.

Watch native memory over time

jcmd <pid> VM.native_memory summary

Interpretation

The summary separates heap from direct and other native regions, revealing growth outside the heap.

Raise the limit as a test

java -XX:MaxDirectMemorySize=1g -jar app.jar

Interpretation

If raising the limit delays the error, the workload genuinely needs more direct memory or leaks buffers.

Root cause

Direct ByteBuffer allocations exceeded MaxDirectMemorySize because they were allocated faster than they could be reclaimed, or because references were held, so native memory ran out even though the heap was healthy.

Fix

Release or reuse direct buffers, cap pooled allocations, and size MaxDirectMemorySize to the real workload. Investigate leaks by tracking allocation sites rather than only raising the limit.

Verify the fix

Run the workload again and confirm direct memory stays below the limit with Native Memory Tracking, and confirm the OutOfMemoryError no longer occurs.

Symptom walkthrough

The JVM throws OutOfMemoryError: Direct buffer memory while heap statistics look healthy. Direct ByteBuffers live in native memory outside the heap, so a heap dump shows nothing wrong even as the process grows. High-throughput network or file IO that allocates direct buffers, and pooled allocators such as those in Netty, are common sources.

Fix in practice

Track direct memory with Native Memory Tracking and the native memory summary, then reduce or reuse direct allocations and cap pooling. Size MaxDirectMemorySize for the real workload, and if usage keeps growing, hunt for buffers whose references outlive their use rather than only raising the limit.

Verification

Rerun the workload and confirm direct memory stays below the limit by inspecting the native memory summary, and confirm the error does not recur. Stable native memory under load confirms the fix.

Diagnostic commands

Check the behavior with commands like these:

java -XX:MaxDirectMemorySize=256m -XX:+PrintNMTStatistics -jar app.jar
jcmd <pid> VM.native_memory summary
java -XX:MaxDirectMemorySize=1g -jar app.jar