oracle/graal · error · IllegalArgumentException

For instance methods, the receiver argument must not represe

Error message

For instance methods, the receiver argument must not represent a null constant

What it means

Thrown by HostVMAccess.invoke when an instance method is invoked with a JavaConstant that itself represents null (JavaConstant.isNull()). The API distinguishes 'no receiver reference' (null) from 'receiver is the null constant' — for instance calls the latter is meaningless because reflection cannot dispatch invoke on a null object.

Source

Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:147

    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 {
                    unboxedArguments[i] = snippetReflection.asObject(parameterTypes[i], argument);
                    if (unboxedArguments[i] == null) {
                        throw new IllegalArgumentException(
                                        "Illegal argument type: arguments[" + i + "] of type " + providers.getMetaAccess().lookupJavaType(arguments[i]).toClassName() +
                                                        " could not be converted to a " + parameterTypes[i]);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Guard before invoking: if receiver != null && receiver.isNull(), either skip the call, substitute a real object, or let the caller's NPE semantics apply at the guest level
  2. Use forObject only for non-null objects and pass null only when the method is static/constructor
  3. If the guest program legitimately calls an instance method on null, raise/propagate the guest NullPointerException instead of invoking the host

Example fix

// before
hostVM.invoke(instanceMethod, snippetReflection.forObject(maybeNull), args);  // null constant -> throws

// after
JavaConstant receiver = maybeNull == null ? null : snippetReflection.forObject(maybeNull);
if (receiver != null && receiver.isNull()) {
    throw new NullPointerException("receiver is null"); // explicit guest semantics
}
hostVM.invoke(instanceMethod, receiver, args);
Defensive patterns

Strategy: type-guard

Validate before calling

if (receiver != null && receiver.isNull()) { /* null receiver constant: do not invoke */ }

Type guard

static boolean isNullConstant(JavaConstant c) { return c == null || c.isNull(); }

Try / catch

catch (IllegalArgumentException e) { convert to guest NullPointerException if the guest called a method on null }

Prevention

When it happens

Trigger: Calling invoke(instanceMethod, JavaConstant.NULL_POINTER, args...) or any receiver constant whose isNull() is true, for a non-static executable.

Common situations: Uniform code that wraps possibly-null objects with snippetReflection.forObject(x) — forObject(null) yields the null constant, which is then forwarded as receiver; unfolding a snippet where the receiver was a null-folded constant.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/11a8b604443a1144. Report an issue: GitHub.