java-native-access/jna · error · IllegalArgumentException

Interface ( ) of library= does not extend Library

Error message

Interface (<interfaceSimpleName>) of library=<name> does not extend Library

What it means

Native.load() requires the interface it wraps to extend com.sun.jna.Library so the proxy Handler can treat it as a native library mapping. If Library.class.isAssignableFrom(interfaceClass) is false, JNA throws IllegalArgumentException naming the interface and library.

Solutions

  1. Make the interface extend com.sun.jna.Library: interface MyLib extends Library { ... }.
  2. If the type genuinely is not a library mapping, use the correct JNA API instead of Native.load.
  3. Check generics so the compiler enforces <T extends Library> at the call site.

Example fix

// before
public interface CLib { int getpid(); }
CLib lib = Native.load("c", CLib.class); // IllegalArgumentException
// after
public interface CLib extends com.sun.jna.Library { int getpid(); }
CLib lib = Native.load("c", CLib.class);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Library.class.isAssignableFrom(ifaceClass)) {
    throw new IllegalArgumentException(ifaceClass + " must extend Library before Native.load");
}
T lib = Native.load(name, ifaceClass, options);

Type guard

<T> boolean isLibraryMapping(Class<T> c) {
    return Library.class.isAssignableFrom(c);
}

Try / catch

try {
    lib = Native.load(name, ifaceClass, options);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Define " + ifaceClass.getSimpleName()
        + " as 'interface X extends Library': " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling Native.load(name, SomeInterface.class, options) where SomeInterface does not declare 'extends Library' — e.g. a plain interface of native methods, or extending the wrong marker interface.

Common situations: Migrating from loadLibrary to load and forgetting the extends Library clause; copying a mapped interface but dropping the Library parentage; defining the interface in a shared module without the JNA dependency hierarchy.

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

Appendix: source

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

     * the explicit interface class and a map of options for the library.
     * If no library options are detected the map is interpreted as a map
     * of Java method names to native function names.<p>
     * If <code>name</code> is null, attempts to map onto the current process.
     * Native libraries loaded via this method may be found in
     * <a href="NativeLibrary.html#library_search_paths">several locations</a>.
     * @param <T> Type of expected wrapper
     * @param name Library base name
     * @param interfaceClass The implementation wrapper interface
     * @param options Map of library options
     * @return an instance of the requested interface, mapped to the indicated
     * native library.
     * @throws UnsatisfiedLinkError if the library cannot be found or
     * dependent libraries are missing.
     */
    public static <T extends Library> T load(String name, Class<T> interfaceClass, Map<String, ?> options) {
        if (!Library.class.isAssignableFrom(interfaceClass)) {
            // Maybe still possible if the caller is not using generics?
            throw new IllegalArgumentException("Interface (" + interfaceClass.getSimpleName() + ")"
                    + " of library=" + name + " does not extend " + Library.class.getSimpleName());
        }

        Library.Handler handler = new Library.Handler(name, interfaceClass, options);
        ClassLoader loader = interfaceClass.getClassLoader();
        Object proxy = Proxy.newProxyInstance(loader, new Class[] {interfaceClass}, handler);
        cacheOptions(interfaceClass, options, proxy);
        return interfaceClass.cast(proxy);
    }

    /**
     * Provided for improved compatibility between JNA 4.X and 5.X
     *
     * @see Native#load(java.lang.Class)
     */
    @Deprecated
    public static <T> T loadLibrary(Class<T> interfaceClass) {
        return loadLibrary(null, interfaceClass);

View on GitHub (pinned to d036ad9781)