oracle/graal · error · IllegalArgumentException
For static methods or constructor, the receiver argument…
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.
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
- Could not obtain the original class for
- Expected value kind but got
- For instance fields, the receiver argument must not be null
- For instance fields, the receiver argument must not…
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1d4486c75350a6eb.
Report an issue: GitHub.
Appendix: 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)