java-native-access/jna · error · java.lang.IllegalArgumentException

Structure array elements must use contiguous memory (bad bac

Error message

Structure array elements must use contiguous memory (bad backing address at Structure array index 

What it means

Before operating on an array of Structures as a contiguous native block, Structure.structureArrayCheck verifies that every element's backing native address equals base + index*size. If an element was allocated separately (its own Memory/auto-allocated pointer) the array is not contiguous and marshalling the whole array would corrupt data, so it throws IllegalArgumentException naming the first offending index.

Source

Thrown at src/com/sun/jna/Structure.java:2322

            super.clear();
        }
        @Override
        public String toString() {
            return "auto-" + super.toString();
        }
    }

    private static void structureArrayCheck(Structure[] ss) {
        if (Structure.ByReference[].class.isAssignableFrom(ss.getClass())) {
            return;
        }
        Pointer base = ss[0].getPointer();
        int size = ss[0].size();
        for (int si=1;si < ss.length;si++) {
            if (ss[si].getPointer().peer != base.peer + size*si) {
                String msg = "Structure array elements must use"
                    + " contiguous memory (bad backing address at Structure array index " + si + ")";
                throw new IllegalArgumentException(msg);
            }
        }
    }

    public static void autoRead(Structure[] ss) {
        structureArrayCheck(ss);
        if (ss[0].array == ss) {
            ss[0].autoRead();
        }
        else {
            for (int si=0;si < ss.length;si++) {
                if (ss[si] != null) {
                    ss[si].autoRead();
                }
            }
        }
    }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Allocate the array contiguously with s = (S)new S().toArray(size) and use those elements, instead of constructing each element with its own memory
  2. If elements must live at separate addresses, pass them individually (or as an array of pointers ByReference) rather than as one Structure[] native block
  3. Never call useMemory() on elements after forming a Structure[]; keep one shared backing Memory for the whole array
  4. Verify element pointers before marshalling: check ss[i].getPointer().peer offsets yourself when attaching to foreign memory

Example fix

// before
MyStruct[] arr = new MyStruct[n];
for (int i=0;i<n;i++) arr[i] = new MyStruct(new Memory(size)); // non-contiguous
// after
MyStruct[] arr = (MyStruct[]) new MyStruct().toArray(n); // contiguous backing
Defensive patterns

Strategy: validation

Validate before calling

<S extends Structure> boolean isContiguous(S[] ss) {
    if (ss == null || ss.length == 0) return true;
    Pointer base = ss[0].getPointer();
    long size = ss[0].size();
    for (int i = 1; i < ss.length; i++) {
        if (ss[i].getPointer().peer != base.peer + size * i) return false;
    }
    return true;
}

Try / catch

try {
    Structure.autoRead(array);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("contiguous memory")) {
        throw new IllegalStateException("Reallocate array with new MyStruct().toArray(n)");
    }
    throw e;
}

Prevention

When it happens

Trigger: Creating Structure elements with individual new Memory(...) pointers, mixing auto-allocated elements with a shared backing buffer, using Structure.toArray on elements that were separately attached to foreign memory, or modifying one element's pointer after array creation.

Common situations: Manually calling useMemory() on individual elements of what is intended to be one array, reusing Structure objects allocated earlier at different addresses inside an array, or building an array from structures returned by native code at scattered addresses and then passing it as a native array.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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