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
- Make the interface extend com.sun.jna.Library: interface MyLib extends Library { ... }.
- If the type genuinely is not a library mapping, use the correct JNA API instead of Native.load.
- 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
- Always declare native-library interfaces as 'interface X extends Library'.
- Let the <T extends Library> generic bound catch mistakes at compile time by typing helper methods correctly.
- Never bypass the generic bound with raw Class arguments.
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
- Callback type must be an interface
- Function declared Structure[] at parameter but array of was…
- Function declared Structure[] at parameter but element is…
- Insufficient memory to align to the requested boundary
- does not implement an interface
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)