java-native-access/jna · error · IllegalStateException
Can't autogenerate a direct buffer on memory read
Error message
Can't autogenerate a direct buffer on memory read
What it means
Pointer.getValue throws IllegalStateException when reading a Buffer-typed value from memory: JNA cannot materialize a new direct ByteBuffer for the read; it only returns an existing initialized direct Buffer whose backing native pointer matches the memory being read. Autogenerating a buffer during a read is not allowed.
Solutions
- Initialize the field with a direct ByteBuffer: ByteBuffer.allocateDirect(n) before reading
- Use Pointer.getByteBuffer(offset, size) explicitly instead of getValue with Buffer.class
- Ensure the same direct buffer instance is reused and not reallocated between calls
- Use Pointer/byte[] types in structures if readback of new memory is needed
Example fix
// before ByteBuffer buf; // null or heap buffer Pointer.getValue(offset, ByteBuffer.class, buf); // after ByteBuffer buf = ByteBuffer.allocateDirect(64); pointer.getValue(offset, ByteBuffer.class, buf); // returns same buffer
Defensive patterns
Strategy: validation
Validate before calling
if (buf == null || !buf.isDirect()) {
buf = ByteBuffer.allocateDirect(size);
} Type guard
static boolean isDirectBuffer(Object o) {
return o instanceof Buffer && ((Buffer) o).isDirect();
} Prevention
- Always pre-initialize Buffer-typed structure fields with direct buffers
- Never reallocate a buffer whose pointer JNA has already captured
- Use getByteBuffer(offset, size) for one-off reads
When it happens
Trigger: Calling Pointer.getValue(offset, Buffer.class, currentValue) where currentValue is null or a Buffer whose Native.getDirectBufferPointer does not equal the pointer at this offset.
Common situations: Reading a Structure field typed as Buffer that was never initialized with a direct ByteBuffer; passing a heap (non-direct) buffer like ByteBuffer.allocate instead of allocateDirect; buffer's native pointer changed after reallocation.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Need an initialized array
- Allocation size must be greater than zero
- Area is not polygonal: " + area
- Argument value 0x exceeds native capacity ( bytes) mask=0x
- Array fields must be initialized
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/ea219cf3f4fe9666.
Report an issue: GitHub.
Appendix: source
Thrown at src/com/sun/jna/Pointer.java:428
if (fp == null) {
result = null;
} else {
Callback cb = (Callback)currentValue;
Pointer oldfp = CallbackReference.getFunctionPointer(cb);
if (!fp.equals(oldfp)) {
cb = CallbackReference.getCallback(type, fp);
}
result = cb;
}
} else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) {
Pointer bp = getPointer(offset);
if (bp == null) {
result = null;
} else {
Pointer oldbp = currentValue == null ? null
: Native.getDirectBufferPointer((Buffer)currentValue);
if (oldbp == null || !oldbp.equals(bp)) {
throw new IllegalStateException("Can't autogenerate a direct buffer on memory read");
}
result = currentValue;
}
} else if (NativeMapped.class.isAssignableFrom(type)) {
NativeMapped nm = (NativeMapped)currentValue;
if (nm != null) {
Object value = getValue(offset, nm.nativeType(), null);
result = nm.fromNative(value, new FromNativeContext(type));
if (nm.equals(result)) {
result = nm;
}
} else {
NativeMappedConverter tc = NativeMappedConverter.getInstance(type);
Object value = getValue(offset, tc.nativeType(), null);
result = tc.fromNative(value, new FromNativeContext(type));
}
} else if (type.isArray()) {
result = currentValue;View on GitHub (pinned to d036ad9781)