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

  1. Fix the offset computation so it is non-negative; check the arithmetic that produced it.
  2. Validate offsets before access: if (off < 0) handle/throw a clearer error.
  3. If working with a sub-region, use Memory.share(offset, size) with correct bounds instead of manual offset math.
  4. 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

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


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/90a6a6c8d9bb2bea. Report an issue: GitHub.