java-native-access/jna · critical · OutOfMemoryError
Cannot allocate <size> bytes
Error message
Cannot allocate <size> bytes
What it means
The Memory constructor throws this OutOfMemoryError when the underlying native malloc returns NULL (peer == 0), i.e. the OS/native allocator could not provide `size` bytes. Unlike a Java heap OOM, this reflects native heap exhaustion.
Source
Thrown at src/com/sun/jna/Memory.java:119
@Override
public String toString() {
return super.toString() + " (shared from " + Memory.this.toString() + ")";
}
}
/**
* Allocate space in the native heap via a call to C's <code>malloc</code>.
*
* @param size number of <em>bytes</em> of space to allocate
*/
public Memory(long size) {
this.size = size;
if (size <= 0) {
throw new IllegalArgumentException("Allocation size must be greater than zero");
}
peer = malloc(size);
if (peer == 0)
throw new OutOfMemoryError("Cannot allocate " + size + " bytes");
allocatedMemory.put(peer, new WeakReference<>(this));
cleanable = Cleaner.getCleaner().register(this, new MemoryDisposer(peer));
}
protected Memory() {
super();
cleanable = null;
}
/** Provide a view of this memory using the given offset as the base address. The
* returned {@link Pointer} will have a size equal to that of the original
* minus the offset.
* @throws IndexOutOfBoundsException if the requested memory is outside
* the allocated bounds.
*/
@Override
public Pointer share(long offset) {View on GitHub (pinned to d036ad9781)
Solutions
- Reduce the requested allocation size or allocate in chunks.
- Check process/container memory limits (ulimit, cgroups) and raise them.
- Free Memory deterministically (close()/dispose or rely on explicit cleanup) instead of holding many allocations.
- Switch to a 64-bit JVM/address space if on 32-bit.
- Profile for native leaks; failing malloc after long runs usually means leaked native memory.
Example fix
// before
Memory buf = new Memory(totalSize); // totalSize ~ 4GB, malloc fails
// after
for (Chunk c : chunks) { Memory buf = new Memory(c.size); /* process and release */ } Defensive patterns
Strategy: fallback
Validate before calling
static boolean sizePlausible(long bytes, long maxBytes) { return bytes > 0 && bytes <= maxBytes; } Try / catch
Memory m;
try {
m = new Memory(size);
} catch (OutOfMemoryError e) {
if (e.getMessage().startsWith("Cannot allocate ")) {
m = allocateInChunks(size); // fall back to chunked allocation
} else throw e;
} Prevention
- Cap allocation sizes based on trusted limits, not raw input.
- Monitor native memory (Native.getNativeSize, OS RSS) in long-running apps.
- Free Memory deterministically instead of waiting on the Cleaner.
- Avoid 32-bit JVMs for large native allocations.
- Check container/ulimit memory ceilings.
When it happens
Trigger: new Memory(hugeSize) where the native heap cannot satisfy the request; cumulative native leaks exhausting the process address space; allocating on 32-bit JVMs beyond ~2-4GB addressable space.
Common situations: Allocating buffers sized from untrusted/oversized input; 32-bit processes; many live Memory instances never released (relying on Cleaner) causing native fragmentation/exhaustion; container memory limits making malloc fail.
Related errors
- Win32Exception(Kernel32.INSTANCE.GetLastError())
- Allocation size must be greater than zero
- Byte boundary must be positive: <byteBoundary>
- JNA: Out of memory: Can't allocate local frame
- No support for " + os
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/32ac732eb2f857b1.
Report an issue: GitHub.