java-native-access/jna · error · IllegalArgumentException

Type " + type + " has unknown native alignment"

Error message

Type " + type + " has unknown native alignment"

What it means

Structure.getNativeAlignment() computes the native byte alignment for a field type. If the type is not a primitive, Pointer/Buffer/Callback/String/WString, Structure, NativeMapped, or array, JNA has no rule for it and throws "Type ... has unknown native alignment". This means a field type in the Structure is not mappable to a native type.

Source

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

                 || WString.class == type
                 || String.class == type) {
            alignment = Native.POINTER_SIZE;
        }
        else if (Structure.class.isAssignableFrom(type)) {
            if (ByReference.class.isAssignableFrom(type)) {
                alignment = Native.POINTER_SIZE;
            }
            else {
                if (value == null)
                    value = newInstance((Class<? extends Structure>) type, PLACEHOLDER_MEMORY);
                alignment = ((Structure)value).getStructAlignment();
            }
        }
        else if (type.isArray()) {
            alignment = getNativeAlignment(type.getComponentType(), null, isFirstElement);
        }
        else {
            throw new IllegalArgumentException("Type " + type + " has unknown "
                                               + "native alignment");
        }
        if (actualAlignType == ALIGN_NONE) {
            alignment = 1;
        }
        else if (actualAlignType == ALIGN_MSVC) {
            alignment = Math.min(8, alignment);
        }
        else if (actualAlignType == ALIGN_GNUC) {
            // NOTE this is published ABI for 32-bit gcc/linux/x86, osx/x86,
            // and osx/ppc.  osx/ppc special-cases the first element
            if (!isFirstElement || !(Platform.isMac() && Platform.isPPC())) {
                alignment = Math.min(Native.MAX_ALIGNMENT, alignment);
            }
            if (!isFirstElement && Platform.isAIX() && (type == double.class || type == Double.class)) {
                alignment = 4;
            }
        }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Replace the field with a JNA-supported type (primitive, Pointer, String/WString, Buffer, Callback, array, or nested Structure).
  2. If the custom type maps to a native value, implement NativeMapped (with NativeMappedConverter) on that class so getNativeAlignment can resolve its nativeType().
  3. Register a TypeMapper (e.g. via Structure setTypeMapper or a library-level mapper) converting the unsupported class to a supported one.
  4. If it should be an opaque handle, use com.sun.jna.PointerType or Pointer.ByReference instead of the arbitrary object type.

Example fix

// before
public class Status { private int code; } // POJO field
public Status status;
// after
public class Status extends IntegerType implements NativeMapped { public Status() { super(4, true); this.code = 0; } }
public Status status;
Defensive patterns

Strategy: type-guard

Validate before calling

static void validateFieldTypes(Class<? extends Structure> cls) {
    for (Field f : cls.getDeclaredFields()) {
        Class<?> t = f.getType();
        boolean ok = t.isPrimitive() || Pointer.class.isAssignableFrom(t) || Structure.class.isAssignableFrom(t)
            || t.isArray() || String.class == t || WString.class == t
            || Buffer.class.isAssignableFrom(t) || Callback.class.isAssignableFrom(t)
            || NativeMapped.class.isAssignableFrom(t);
        if (!ok) throw new IllegalStateException("Field " + f + " has unsupported native type " + t);
    }
}

Type guard

static boolean hasKnownNativeAlignment(Class<?> t) {
    return t.isPrimitive() || Pointer.class.isAssignableFrom(t)
        || Structure.class.isAssignableFrom(t) || t.isArray()
        || String.class == t || WString.class == t
        || Buffer.class.isAssignableFrom(t) || Callback.class.isAssignableFrom(t)
        || NativeMapped.class.isAssignableFrom(t);
}

Try / catch

try {
    MyStruct s = new MyStruct();
    int size = s.size();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("unknown native alignment")) {
        throw new IllegalStateException("Replace unsupported field type named in: " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Declaring a Structure field whose Java type is not one of JNA's supported types (e.g. java.math.BigInteger, a POJO, java.util.Date, a generic Object) and is not covered by a NativeMapped or TypeMapper conversion, then triggering layout calculation (instantiation, getSize(), or a native call).

Common situations: Migrating a struct field from int to a wrapper/POJO type; forgetting a TypeMapper/@Structure.FieldOrder mapping for a custom class; passing a Collection or Optional as a struct field; auto-generated struct classes containing unsupported JDK types.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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