java-native-access/jna · error · IllegalArgumentException
Unsupported type " + cls
Error message
Unsupported type " + cls
What it means
Structure.getTypeInfo(Object, Class) maps Java field values to libffi FFIType descriptors for a known set of types (primitives, boxed types, Pointer, String, WString, arrays, Structure, Callback, etc.). If the class is not one of the supported native-mappable types, it throws IllegalArgumentException with "Unsupported type <cls>".
Source
Thrown at src/com/sun/jna/Structure.java:2266
}
}
finally {
cacheStructureLock.writeLock().unlock();
}
if (NativeMapped.class.isAssignableFrom(cls)) {
NativeMappedConverter c = NativeMappedConverter.getInstance(cls);
return get(c.toNative(obj, new ToNativeContext()), c.nativeType());
}
if (cls.isArray()) {
FFIType type = new FFIType(obj, cls);
// Store it in the map to prevent premature GC of type info
storeTypeInfo(cls, Array.getLength(obj), type);
return type;
}
throw new IllegalArgumentException("Unsupported type " + cls);
}
private static FFIType getTypeInfo(Class clazz, int elementCount) {
cacheStructureLock.readLock().lock();
try {
Map<Integer, FFIType> typeMap = typeInfoMap.get(clazz);
if (typeMap != null) {
return typeMap.get(elementCount);
} else {
return null;
}
}
finally {
cacheStructureLock.readLock().unlock();
}
}
private static void storeTypeInfo(Class clazz, FFIType type) {View on GitHub (pinned to d036ad9781)
Solutions
- Change the Structure field to a natively mappable type (int, long, double, boolean, byte/short/char, Pointer, String, WString, nested Structure, arrays, or ByReference variants)
- If the field has a natural native representation, provide a custom TypeMapper (or @Structure.FieldOrder-safe mapper/ToNativeConverter) registered via Native.setTypeMapper or the Structure constructor
- For complex data, flatten into supported primitives or pass as a nested Structure/Pointer with explicit marshalling
- Check which field triggers it: the message names the exact class; compare against Structure.FFIType-supported types in the JNA docs
Example fix
// before
public class S extends Structure {
public BigDecimal amount; // Unsupported type java.math.BigDecimal
}
// after
public class S extends Structure {
public long amountCents; // map in application code
} Defensive patterns
Strategy: type-guard
Validate before calling
// JNA-supported native-mappable field types (Java types usable directly in Structures)
Set<Class<?>> NATIVE_TYPES = new HashSet<>(Arrays.asList(
boolean.class, byte.class, short.class, char.class, int.class,
long.class, float.class, double.class,
Boolean.class, Byte.class, Short.class, Character.class, Integer.class,
Long.class, Float.class, Double.class,
Pointer.class, String.class, WString.class));
void checkFields(Class<?> s) {
for (Field f : s.getFields()) {
Class<?> t = f.getType();
if (!NATIVE_TYPES.contains(t) && !Structure.class.isAssignableFrom(t)
&& !Callback.class.isAssignableFrom(t) && !t.isArray()
&& !FromNativeConverter.class.isAssignableFrom(t)) {
throw new IllegalArgumentException("Field not natively mappable: " + f);
}
}
} Type guard
boolean isNativeMappable(Class<?> t) {
return t.isPrimitive()
|| Number.class.isAssignableFrom(t) || t == Boolean.class || t == Character.class
|| t == Pointer.class || t == String.class || t == WString.class
|| Structure.class.isAssignableFrom(t) || Callback.class.isAssignableFrom(t)
|| t.isArray();
} Try / catch
try {
structure.read();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unsupported type ")) {
throw new IllegalStateException("Replace/natively map field of type: "
+ e.getMessage().substring("Unsupported type ".length()), e);
}
throw e;
} Prevention
- Only use primitives, boxed primitives, Pointer, String/WString, arrays, nested Structures, or Callbacks as Structure fields
- Register a TypeMapper/ToNativeConverter for any custom field type
- Run Native.getNativeSize(structureClass) in a unit test to catch unsupported fields early
When it happens
Trigger: Declaring a Structure field of a type JNA cannot map to native memory (e.g. java.math.BigDecimal, java.util.Date, an arbitrary POJO, or an unsupported generic type) and then reading/writing the structure or calling Native.getNativeSize on it.
Common situations: Mapping a struct that contains a field type not supported by JNA (auto-boxed custom wrappers, Optional, collections), refactoring a field from a supported type to an unsupported one, or forgetting a TypeMapper/Structure.FieldOffset mapping for the field.
Related errors
- The type "type.getName()" is not supported: e.getMessage()
- Native size for type "cls.getName()" is unknown
- Invalid Structure field in " + getClass() + ", field name '"
- Type " + type + " has unknown native alignment"
- Unsupported empty type:
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/5eb97d561889d2d0.
Report an issue: GitHub.