oracle/graal · error · IllegalArgumentException
For static methods or constructor, the receiver argument mus
Error message
For static methods or constructor, the receiver argument must be null
What it means
Thrown by HostVMAccess.invoke when invoking a static method or a constructor with a non-null receiver JavaConstant. Reflection semantics require no receiver for static/constructor execution, so this is an API-contract violation by the caller, not a runtime failure of the target code.
Source
Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:142
public boolean owns(ResolvedJavaMethod value) {
return value.getClass().getModule() == hostImplModule;
}
@Override
public boolean owns(ResolvedJavaField value) {
return value.getClass().getModule() == hostImplModule;
}
@Override
public JavaConstant invoke(ResolvedJavaMethod method, JavaConstant receiver, JavaConstant... arguments) {
SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();
Executable executable = snippetReflection.originalMethod(method);
makeAccessible(executable);
boolean isConstructor = executable instanceof Constructor;
Class<?>[] parameterTypes = executable.getParameterTypes();
if (Modifier.isStatic(executable.getModifiers()) || isConstructor) {
if (receiver != null) {
throw new IllegalArgumentException("For static methods or constructor, the receiver argument must be null");
}
} else if (receiver == null) {
throw new NullPointerException("For instance methods, the receiver argument must not be null");
} else if (receiver.isNull()) {
throw new IllegalArgumentException("For instance methods, the receiver argument must not represent a null constant");
}
if (parameterTypes.length != arguments.length) {
throw new IllegalArgumentException("Wrong number of arguments: expected " + parameterTypes.length + " but got " + arguments.length);
}
Signature signature = method.getSignature();
Object[] unboxedArguments = new Object[parameterTypes.length];
for (int i = 0; i < unboxedArguments.length; i++) {
JavaKind parameterKind = signature.getParameterKind(i);
JavaConstant argument = arguments[i];
if (parameterKind.isObject()) {
if (argument.isNull()) {
unboxedArguments[i] = null;
} else {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Pass null as receiver when the executable is static or a constructor
- Branch on Modifier.isStatic(executable.getModifiers()) / instanceof Constructor before building the call, mirroring the guard in HostVMAccess
- If you expected an instance method, verify the ResolvedJavaMethod really resolves to a non-static original via SnippetReflectionProvider.originalMethod
Example fix
// before
hostVM.invoke(staticMethod, snippetReflection.forObject(obj), args); // throws
// after
Object receiverConst = Modifier.isStatic(executable.getModifiers()) || executable instanceof Constructor
? null
: snippetReflection.forObject(obj);
hostVM.invoke(staticMethod, receiverConst, args); Defensive patterns
Strategy: validation
Validate before calling
Executable ex = snippetReflection.originalMethod(method);
boolean noReceiver = Modifier.isStatic(ex.getModifiers()) || ex instanceof Constructor;
if (noReceiver && receiver != null) throw new IllegalArgumentException("receiver must be null"); Type guard
static boolean takesReceiver(Executable ex) { return !Modifier.isStatic(ex.getModifiers()) && !(ex instanceof Constructor); } Try / catch
catch (IllegalArgumentException e) { fail fast with the executable identity in the message } Prevention
- Always branch on staticness/constructor before constructing the receiver
- Centralize invoke calls in one helper that owns the receiver rule
- Never forward a 'default' receiver constant blindly
When it happens
Trigger: Calling invoke(method, receiver, args...) where method maps to a static Executable or a Constructor and receiver is any non-null JavaConstant (even JavaConstant.NULL_POINTER counts as non-null here).
Common situations: Generic invocation code that always forwards a receiver constant (e.g. a snippet host or a test harness that reuses one call path for instance and static methods), or misclassifying a method as instance because Modifier.isStatic was checked on the wrong mirror after snippet substitution.
Related errors
- For static fields, the receiver argument must be null
- For instance methods, the receiver argument must not be null
- For instance methods, the receiver argument must not represe
- Wrong number of arguments: expected {} but got {}
- Illegal argument type: arguments[{}] of type {} could not be
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1d4486c75350a6eb.
Report an issue: GitHub.