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
- Replace the field with a JNA-supported type (primitive, Pointer, String/WString, Buffer, Callback, array, or nested Structure).
- If the custom type maps to a native value, implement NativeMapped (with NativeMappedConverter) on that class so getNativeAlignment can resolve its nativeType().
- Register a TypeMapper (e.g. via Structure setTypeMapper or a library-level mapper) converting the unsupported class to a supported one.
- 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
- Restrict Structure fields to JNA-mappable types; model handles with Pointer/PointerType and integers with IntegerType
- Implement NativeMapped for custom value classes so they resolve to a native type
- Run a smoke test that allocates every Structure at startup to surface layout errors before native calls
- Remember error message includes the offending type name - check it first when debugging
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
- Field alignment is zero for field '" + structField.name + "'
- Can't determine size of nested structure
- Unsupported type " + cls
- Unsupported empty type:
- Unsupported type:
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/e25933d80170c5b6.
Report an issue: GitHub.