java-native-access/jna · error · IllegalArgumentException

Byte boundary must be a power of two

Error message

Byte boundary must be a power of two

What it means

Memory.align() only supports byte boundaries that are powers of two (1, 2, 4, 8, 16...), because it computes the aligned address with a bitmask (~boundary-1). Any other value cannot produce a valid mask, so JNA falls through the loop and throws IllegalArgumentException.

Source

Thrown at src/com/sun/jna/Memory.java:181

        if (byteBoundary <= 0) {
            throw new IllegalArgumentException("Byte boundary must be positive: " + byteBoundary);
        }
        for (int i=0;i < 32;i++) {
            if (byteBoundary == (1<<i)) {
                long mask = ~((long)byteBoundary - 1);

                if ((peer & mask) != peer) {
                    long newPeer = (peer + byteBoundary - 1) & mask;
                    long newSize = peer + size - newPeer;
                    if (newSize <= 0) {
                        throw new IllegalArgumentException("Insufficient memory to align to the requested boundary");
                    }
                    return (Memory)share(newPeer - peer, newSize);
                }
                return this;
            }
        }
        throw new IllegalArgumentException("Byte boundary must be a power of two");
    }

    /** Free the native memory and set peer to zero */
    @Override
    public void close() {
        peer = 0;
        if (cleanable != null) {
            cleanable.clean();
        }
    }

    @Deprecated
    protected void dispose() {
        close();
    }

    /** Zero the full extent of this memory region. */
    public void clear() {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Pass a power-of-two boundary: use Integer.highestOneBit(n) or the next power of two ≥ n.
  2. Use a standard alignment constant (1, 2, 4, 8, 16).
  3. Guard the call: if (Integer.bitCount(boundary) != 1) pick a valid boundary before aligning.

Example fix

// before
Memory aligned = mem.align(6); // IllegalArgumentException
// after
int boundary = Integer.highestOneBit(6) * 2; // 8, next power of two
Memory aligned = mem.align(boundary);
Defensive patterns

Strategy: validation

Validate before calling

if (boundary <= 0 || Long.bitCount(boundary) != 1) {
    throw new IllegalArgumentException("boundary must be a positive power of two: " + boundary);
}
Memory aligned = memory.align(boundary);

Type guard

boolean isPowerOfTwo(long n) {
    return n > 0 && (n & (n - 1)) == 0;
}

Try / catch

try {
    aligned = memory.align(boundary);
} catch (IllegalArgumentException e) {
    long next = Long.highestOneBit(boundary) * 2; // round up to next power of two
    aligned = memory.align(next);
}

Prevention

When it happens

Trigger: Calling memory.align(n) or aligned(n) where n is not a power of two, e.g. align(3), align(6), align(0), or a negative value — the while loop (boundary >= 2, halving) never matches and control reaches the throw.

Common situations: Passing a struct size or alignment guess like 3 or 6 instead of the next power of two; typos such as align(10); unit tests testInvalidAlignment exercising invalid boundaries.

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/e2580ccf588d9fd2. Report an issue: GitHub.