java-native-access/jna · error · java.lang.IllegalArgumentException
library object passed to getNativeLibrary in not a proxy
Error message
library object passed to getNativeLibrary in not a proxy
What it means
Native.getNativeLibrary(Library) requires a JDK dynamic proxy created by Native.load(); any other object throws this IllegalArgumentException. The check is Proxy.isProxyClass(library.getClass()), which fails for hand-written implementations or mocks.
Source
Thrown at src/com/sun/jna/Native.java:2041
registeredClasses.put(cls, handles);
registeredLibraries.put(cls, lib);
}
}
/**
* Get the {@link NativeLibrary} instance that is wrapped by the given
* {@link Library} interface instance.
*
* @param library the {@link Library} interface instance, which was created
* by the {@link Native#load Native.load()} method
* @return the wrapped {@link NativeLibrary} instance
*/
public static NativeLibrary getNativeLibrary(final Library library) {
if(library == null) {
throw new IllegalArgumentException("null passed to getNativeLibrary");
}
if(! Proxy.isProxyClass(library.getClass())) {
throw new IllegalArgumentException("library object passed to getNativeLibrary in not a proxy");
}
final InvocationHandler handler = Proxy.getInvocationHandler(library);
if (!(handler instanceof Library.Handler)) {
throw new IllegalArgumentException("Object is not a properly initialized Library interface instance");
}
return ((Library.Handler) handler).getNativeLibrary();
}
/**
* Get the {@link NativeLibrary} instance to which the given "registered"
* class is bound.
*
* @param cls the "registered" class, which was previously registered via
* the {@link Native#register register()} method
* @return the {@link NativeLibrary} instance to which the "registered"
* class is bound
*/
public static NativeLibrary getNativeLibrary(final Class<?> cls) {View on GitHub (pinned to d036ad9781)
Solutions
- Pass only the object returned by Native.load()/Native.loadLibrary().
- In tests, test against the interface returned from load() rather than a mock of Library, or abstract the accessor behind your own seam.
- Check the call path for accidental wrapping/unwrapping before the getNativeLibrary call.
Example fix
// before
MyLib lib = new MyLibImpl(); // not a JNA proxy
NativeLibrary nl = Native.getNativeLibrary(lib);
// after
MyLib lib = Native.load("mylib", MyLib.class);
NativeLibrary nl = Native.getNativeLibrary(lib); Defensive patterns
Strategy: type-guard
Validate before calling
if (!Proxy.isProxyClass(lib.getClass())) {
throw new IllegalStateException("Pass the object returned by Native.load(), not "
+ lib.getClass().getName());
} Type guard
boolean isJnaLibraryProxy(Object o) {
return o != null && Proxy.isProxyClass(o.getClass())
&& Proxy.getInvocationHandler(o) instanceof Library.Handler;
} Try / catch
try {
NativeLibrary nl = Native.getNativeLibrary(lib);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("not a proxy")) {
throw new IllegalStateException("Use the Native.load()-returned proxy", e);
}
throw e;
} Prevention
- Only call getNativeLibrary with the exact object returned from Native.load().
- Avoid mocks/decorators at the layer that unwraps the NativeLibrary.
- Capture NativeLibrary.getInstance() separately at load time if you need it elsewhere.
When it happens
Trigger: Passing a concrete class, anonymous implementation, Mockito/EasyMock mock, or a proxy from another framework (e.g. cglib, Spring) that implements the Library interface.
Common situations: Unit tests substituting mocks for the loaded library; wrapping the library in a decorator; using a JDK dynamic proxy created by unrelated code.
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
- must be set from byte[]
- Unexpected registry type + lpType.getValue() + , expected RE
- Unexpected registry type + lpType.getValue() + , expected RE
- Unexpected registry type {}, expected REG_SZ
- Unexpected registry type {}, expected REG_BINARY
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/370e788461c064a9.
Report an issue: GitHub.