java-native-access/jna · error · IllegalArgumentException
Callback must implement a single public method, or one publi
Error message
Callback must implement a single public method, or one public method named 'callback'
What it means
IllegalArgumentException thrown by CallbackReference.getCallbackMethod when it cannot determine which method of the callback interface is the native callback entry point. JNA requires the interface to declare exactly one public method, or (if multiple) one named 'callback' (Callback.METHOD_NAME). Otherwise the mapping from Java method to native trampoline is ambiguous and registration fails.
Source
Thrown at src/com/sun/jna/CallbackReference.java:427
Method m = i.next();
if (Callback.FORBIDDEN_NAMES.contains(m.getName())) {
i.remove();
}
}
Method[] methods = pmethods.toArray(new Method[0]);
if (methods.length == 1) {
return checkMethod(methods[0]);
}
for (int i=0;i < methods.length;i++) {
Method m = methods[i];
if (Callback.METHOD_NAME.equals(m.getName())) {
return checkMethod(m);
}
}
String msg = "Callback must implement a single public method, "
+ "or one public method named '" + Callback.METHOD_NAME + "'";
throw new IllegalArgumentException(msg);
}
/** Set the behavioral options for this callback. */
private void setCallbackOptions(int options) {
cbstruct.setInt(Native.POINTER_SIZE, options);
}
/** Obtain a pointer to the native glue code for this callback. */
public Pointer getTrampoline() {
if (trampoline == null) {
trampoline = cbstruct.getPointer(0);
}
return trampoline;
}
/** Free native resources associated with this callback. */
public void close() {
if (cleanable != null) {View on GitHub (pinned to d036ad9781)
Solutions
- Keep callback interfaces to exactly one abstract public method (a functional-interface shape), or
- If multiple methods exist, name the native entry point 'callback' (void callback(Object[] args) style) so JNA can disambiguate.
- Move helper/default methods out of the interface or make them non-public/static; verify with 'javap' or IDE outline that only one public method (or one named 'callback') remains.
Example fix
// before
interface Cb extends Callback {
void invoke(int code);
void log(String s); // second public method -> ambiguous
}
// after
interface Cb extends Callback { void invoke(int code); }
// or
interface Cb2 extends Callback { void callback(Object[] args); } Defensive patterns
Strategy: validation
Validate before calling
static void checkSinglePublicMethod(Class<?> cbType) {
long count = java.util.Arrays.stream(cbType.getMethods())
.filter(m -> !m.isSynthetic() && !m.getDeclaringClass().equals(Object.class))
.filter(m -> m.getName().equals(Callback.METHOD_NAME))
.count();
// require exactly one 'callback' method or a single public method total
} Type guard
static boolean hasDisambiguatedCallback(Class<?> t) {
Method[] ms = t.getMethods();
long named = Arrays.stream(ms).filter(m -> m.getName().equals(Callback.METHOD_NAME)).count();
return named == 1 || Arrays.stream(ms)
.filter(m -> m.getDeclaringClass() != Object.class && !m.isSynthetic()).count() == 1;
} Try / catch
try { registerCallback(cb); } catch (IllegalArgumentException e) { if (e.getMessage().contains("single public method")) { /* reduce to one method or rename to 'callback' */ } throw e; } Prevention
- Keep callback interfaces functional (one abstract method).
- Name the entry method 'callback' when multiple public methods exist.
- Avoid extending extra interfaces that add public methods to callbacks.
- Add a reflective unit test validating each callback interface's shape.
When it happens
Trigger: Registering a callback interface that: declares zero public methods; declares multiple public methods with none named 'callback'; implements several inherited public methods (e.g. extends two interfaces each adding a public method); relies on a method named something other than 'callback' while other public methods exist (e.g. toString-style helpers, Comparable-style methods inherited).
Common situations: Callback interfaces extending other interfaces (adding public default/abstract methods) so more than one public method exists; adding a second helper method to a working single-method callback; lambdas/functions objects whose interface has multiple public members.
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
- Callback argument <nativeParamTypes[i]> requires custom type
- Callback return type <returnType> requires custom type conve
- Method signature exceeds the maximum parameter count: <metho
- <type> is not derived from com.sun.jna.Callback
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/1175d1c1961eec19.
Report an issue: GitHub.