Java — OutOfMemoryError: Direct buffer memory
Diagnose direct buffer exhaustion by tracking native memory use and MaxDirectMemorySize, not only the heap.
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.jarInterpretation
Native Memory Tracking reports direct memory usage, showing whether it approaches the limit.
Watch native memory over time
jcmd <pid> VM.native_memory summaryInterpretation
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.jarInterpretation
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