java-native-access/jna · error · IndexOutOfBoundsException
Invalid offset: <off>
Error message
Invalid offset: <off>
What it means
Memory.boundsCheck() validates every read/write offset against the allocated block. A negative offset can never point into valid malloc'ed space, so JNA throws IndexOutOfBoundsException immediately before any size check.
Source
Thrown at src/com/sun/jna/Memory.java:219
}
/** Returns false if the memory has been freed. */
public boolean valid() {
return peer != 0;
}
public long size() {
return size;
}
/**
* Check that indirection won't cause us to write outside the
* malloc'ed space.
*
*/
protected void boundsCheck(long off, long sz) {
if (off < 0) {
throw new IndexOutOfBoundsException("Invalid offset: " + off);
}
if (off + sz > size) {
String msg = "Bounds exceeds available space : size="
+ size + ", offset=" + (off + sz);
throw new IndexOutOfBoundsException(msg);
}
}
//////////////////////////////////////////////////////////////////////////
// Raw read methods
//////////////////////////////////////////////////////////////////////////
/**
* Indirect the native pointer to <code>malloc</code> space, a la
* <code>Pointer.read</code>. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* <code>malloc</code>ed space to be accessed.
*View on GitHub (pinned to d036ad9781)
Solutions
- Fix the offset computation so it is non-negative; check the arithmetic that produced it.
- Validate offsets before access: if (off < 0) handle/throw a clearer error.
- If working with a sub-region, use Memory.share(offset, size) with correct bounds instead of manual offset math.
- Verify the native pointer you derived the offset from is valid (Pointer.NULL checks).
Example fix
// before
int v = memory.readInt(fieldOffset); // fieldOffset == -8 -> IndexOutOfBoundsException
// after
if (fieldOffset < 0) {
throw new IllegalStateException("bad field offset " + fieldOffset);
}
int v = memory.readInt(fieldOffset); Defensive patterns
Strategy: validation
Validate before calling
if (offset < 0) {
throw new IllegalArgumentException("negative offset: " + offset);
}
memory.readInt(offset); Type guard
boolean validOffset(Memory m, long off, long sz) {
return off >= 0 && off + sz <= m.size();
} Try / catch
try {
value = memory.readInt(offset);
} catch (IndexOutOfBoundsException e) {
log.warn("bad memory offset {}", offset, e);
value = 0; // or rethrow as a domain error
} Prevention
- Compute offsets with unsigned-safe arithmetic; check for negative results after subtraction.
- Use struct classes (Structure) instead of raw offset math where possible.
- Keep base pointer and delta arithmetic in one helper that validates the result.
When it happens
Trigger: Any Memory read/write method (readInt, getPointer, setString, read(offset, buf, 0, len), etc.) called with a negative offset — typically from arithmetic on a bad pointer, a negative share() offset, or unsigned/signed confusion producing a negative long.
Common situations: Computing offsets from struct field offsets that overflowed; passing a negative result of (ptr - base) arithmetic; reading at pointer.getValue() - delta where the pointer was smaller than the delta.
Related errors
- Bounds exceeds available space : size=<size>, offset=<off+sz
- Insufficient memory to align to the requested boundary
- Byte boundary must be a power of two
- Reading \"" + type + "\" from memory is not supported
- Reading array of " + cls + " from memory not supported
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/90a6a6c8d9bb2bea.
Report an issue: GitHub.