java-native-access/jna · error · IllegalArgumentException
Callback method is inaccessible, make sure the interface is
Error message
Callback method is inaccessible, make sure the interface is public: <callbackMethod>
What it means
IllegalArgumentException thrown by DefaultCallbackProxy's constructor when callbackMethod.isAccessible() is false and Method.setAccessible(true) fails with a SecurityException. JNA's generated proxy must invoke the callback method reflectively; if a SecurityManager or module encapsulation (JPMS strong encapsulation) blocks access to a non-public callback interface, registration of the callback cannot proceed. The message explicitly hints that making the interface public usually fixes it.
Source
Thrown at src/com/sun/jna/CallbackReference.java:555
toNative = NativeMappedConverter.getInstance(returnType);
}
else if (mapper != null) {
toNative = mapper.getToNativeConverter(returnType);
}
for (int i=0;i < fromNative.length;i++) {
if (NativeMapped.class.isAssignableFrom(argTypes[i])) {
fromNative[i] = new NativeMappedConverter(argTypes[i]);
}
else if (mapper != null) {
fromNative[i] = mapper.getFromNativeConverter(argTypes[i]);
}
}
if (!callbackMethod.isAccessible()) {
try {
callbackMethod.setAccessible(true);
}
catch(SecurityException e) {
throw new IllegalArgumentException("Callback method is inaccessible, make sure the interface is public: " + callbackMethod);
}
}
}
public Callback getCallback() {
return CallbackReference.this.getCallback();
}
private Object invokeCallback(Object[] args) {
Class<?>[] paramTypes = callbackMethod.getParameterTypes();
Object[] callbackArgs = new Object[args.length];
// convert basic supported types to appropriate Java parameter types
for (int i=0;i < args.length;i++) {
Class<?> type = paramTypes[i];
Object arg = args[i];
if (fromNative[i] != null) {
FromNativeContext context =View on GitHub (pinned to d036ad9781)
Solutions
- Declare the callback interface and its method public (make nested interfaces public static).
- If using JPMS, open/export the package: add 'exports com.example.callbacks;' or 'opens com.example.callbacks;' to module-info.java.
- If a SecurityManager is present, grant the JNA codebase runtime permission suppressAccessChecks, or run without the security manager in trusted environments.
- In OSGi, add the required AllPermission/-suppressAccessChecks via bundle policy or use fragment/extender patterns giving JNA access.
Example fix
// before
interface SecretCb extends Callback { void invoke(int code); } // package-private
// after
public interface SecretCb extends Callback { void invoke(int code); }
// JPMS alternative: add to module-info.java
exports com.example.callbacks; Defensive patterns
Strategy: validation
Validate before calling
static void requireAccessibleCallback(Method m) {
if (!java.lang.reflect.Modifier.isPublic(m.getDeclaringClass().getModifiers()))
throw new IllegalArgumentException("Callback interface must be public: " + m.getDeclaringClass());
} Type guard
static boolean isPubliclyAccessible(Class<?> iface) {
return java.lang.reflect.Modifier.isPublic(iface.getModifiers());
} Try / catch
try { registerCallback(cb); } catch (IllegalArgumentException e) { if (e.getMessage().contains("make sure the interface is public")) { /* make interface public or open the JPMS package */ } throw e; } Prevention
- Make callback interfaces (and nested ones) public static.
- In JPMS, export/open packages containing callbacks.
- Grant suppressAccessChecks to JNA when a SecurityManager is mandatory.
- Test callback registration under the same security/module settings as production.
When it happens
Trigger: Defining a callback interface (or the specific callback method) as non-public (package-private/nested without public) while a SecurityManager policy or Java module system denies setAccessible on it; running under restrictive containers (app servers, OSGi) where JNA's classloader lacks suppressAccessChecks permission; Java 9+ modules hiding a non-exported package containing the callback interface.
Common situations: Package-private callback interfaces inside library code under a SecurityManager; callback interfaces defined inside a non-open JPMS module; OSGi bundles without the required (suppressAccessChecks) DoPrivileged permission; sandboxed plugin environments.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Failed to call addSuppressedMethod
- Error looking up CallbackProxy.callback() method
- Callback type must be an interface
- Callback argument <nativeParamTypes[i]> requires custom type
- Callback return type <returnType> requires custom type conve
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/c5e3270dd52ba779.
Report an issue: GitHub.