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

The type "type.getName()" is not supported: e.getMessage()

Error message

The type "type.getName()" is not supported: e.getMessage()

What it means

Native.getNativeSize(type, value) first handles arrays and structures, then falls back to Native.getNativeSize(type) for the scalar cases it knows (primitives, pointers, etc.). If that fallback throws IllegalArgumentException, the type is simply not a supported JNA native argument type, and the error is rethrown naming the offending class and the underlying reason.

Source

Thrown at src/com/sun/jna/Native.java:1475

    public static int getNativeSize(Class<?> type, Object value) {
        if (type.isArray()) {
            int len = Array.getLength(value);
            if (len > 0) {
                Object o = Array.get(value, 0);
                return len * getNativeSize(type.getComponentType(), o);
            }
            // Don't process zero-length arrays
            throw new IllegalArgumentException("Arrays of length zero not allowed: " + type);
        }
        if (Structure.class.isAssignableFrom(type)
            && !Structure.ByReference.class.isAssignableFrom(type)) {
            return Structure.size((Class<Structure>) type, (Structure)value);
        }
        try {
            return getNativeSize(type);
        }
        catch(IllegalArgumentException e) {
            throw new IllegalArgumentException("The type \"" + type.getName()
                                               + "\" is not supported: "
                                               + e.getMessage());
        }
    }

    /**
     * Returns the native size for a given Java class.  Structures are
     * assumed to be <code>struct</code> pointers unless they implement
     * {@link Structure.ByValue}.
     *
     * @param cls The Java class
     * @return The native size for the class
     */
    public static int getNativeSize(Class<?> cls) {
        if (NativeMapped.class.isAssignableFrom(cls)) {
            cls = NativeMappedConverter.getInstance(cls).nativeType();
        }
        // boolean defaults to 32 bit integer if not otherwise mapped

View on GitHub (pinned to d036ad9781)

Solutions

  1. Map custom data to a JNA-supported type: subclass Structure for C structs, IntegerType for C ints/enums, or use Pointer/ByReference.
  2. Read e.getMessage() in the error — it names the underlying reason from the inner getNativeSize call and usually points at the exact unsupported mapping.
  3. Replace generic Object/POJO parameters in the library interface with primitives, String/WString, arrays, Buffer, Callback, or Structure types.
  4. For opaque native handles, use com.sun.jna.PointerType or Memory instead of a plain Java class.

Example fix

// before
class Config { int flags; } // POJO used as native arg
int query(Config cfg);

// after
class Config extends Structure {
    public int flags;
    @Override protected List<String> getFieldOrder() { return Arrays.asList("flags"); }
}
int query(Config cfg);
Defensive patterns

Strategy: type-guard

Validate before calling

static void requireMappable(Class<?> t) {
    if (!(t.isPrimitive() || Number.class.isAssignableFrom(t) || Structure.class.isAssignableFrom(t)
          || Pointer.class.isAssignableFrom(t) || String.class == t || WString.class == t
          || t.isArray() || Callback.class.isAssignableFrom(t))) {
        throw new IllegalArgumentException("Type not JNA-mappable: " + t);
    }
}

Type guard

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

Try / catch

try {
    int size = Native.getNativeSize(type, value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("is not supported")) {
        throw new IllegalStateException("Change mapping for " + type + " to a Structure/IntegerType/Pointer", e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Passing a Java type JNA cannot map to native — arbitrary POJOs, boxed types in unsupported positions, generic types, interfaces other than JNA's recognized ones — to Native.getNativeSize or as a mapped function/structure-field type.

Common situations: Accidentally mapping a struct field or callback parameter with a custom object type instead of a JNA Structure/IntegerType/pointer, or refactoring a mapped interface after which a previously-primitive parameter became an unsupported type.

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