oracle/graal · error · IllegalArgumentException

Invalid guest type

Error message

Invalid guest type

What it means

createHostProxy builds a java.lang.reflect.Proxy that lets guest code call a host object through a guest-visible interface. It maps guestType back to a host Class via snippetReflection.originalClass and requires that class to exist and be an interface (Proxy.newProxyInstance can only implement interfaces). This IllegalArgumentException ('Invalid guest type') fires when the mapping returns null or a non-interface class.

Source

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

        return switch (kind) {
            case Boolean -> JavaConstant.forBoolean(unsafe.getByte(array, absoluteOffset) != 0);
            case Byte -> JavaConstant.forByte(unsafe.getByte(array, absoluteOffset));
            case Short -> JavaConstant.forShort(unsafe.getShort(array, absoluteOffset));
            case Char -> JavaConstant.forChar(unsafe.getChar(array, absoluteOffset));
            case Int -> JavaConstant.forInt(unsafe.getInt(array, absoluteOffset));
            case Long -> JavaConstant.forLong(unsafe.getLong(array, absoluteOffset));
            case Float -> JavaConstant.forFloat(unsafe.getFloat(array, absoluteOffset));
            case Double -> JavaConstant.forDouble(unsafe.getDouble(array, absoluteOffset));
            default -> throw new IllegalArgumentException("Unsupported kind: " + kind);
        };
    }

    @Override
    public JavaConstant createHostProxy(Object hostTarget, ResolvedJavaType guestType) {
        Objects.requireNonNull(hostTarget);
        Class<?> guestClass = providers.getSnippetReflection().originalClass(Objects.requireNonNull(guestType));
        if (guestClass == null || !guestClass.isInterface()) {
            throw new IllegalArgumentException("Invalid guest type");
        }
        /* There is no fast-path for guestClass == hostClass due to exception handling */
        HostProxyHandler handler = new HostProxyHandler(hostTarget, getHostProxyMethodMap(hostTarget.getClass(), guestClass));
        Object guestHostProxy = Proxy.newProxyInstance(guestClass.getClassLoader(), new Class<?>[]{guestClass}, handler);
        return providers.getSnippetReflection().forObject(guestHostProxy);
    }

    @Override
    public Throwable unwrapHostProxyException(JavaConstant guestWrapper) {
        Objects.requireNonNull(guestWrapper);
        HostProxyExceptionImpl e = providers.getSnippetReflection().asObject(HostProxyExceptionImpl.class, guestWrapper);
        if (e == null) {
            return null;
        }
        return e.getCause();
    }

    private Map<Method, MethodHandle> getHostProxyMethodMap(Class<?> hostClass, Class<?> guestClass) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Pass a ResolvedJavaType that resolves to a host interface: verify originalClass(type) != null && originalClass(type).isInterface() before calling
  2. Extract an interface for the host object's API and use that interface type as guestType
  3. Ensure the guest type comes from the same providers/runtime as this VMAccess so originalClass can map it

Example fix

// before
JavaConstant proxy = vmAccess.createHostProxy(hostObj, concreteClassType); // class, not interface

// after
Class<?> hostIface = providers.getSnippetReflection().originalClass(guestType);
if (hostIface == null || !hostIface.isInterface()) {
    throw new IllegalArgumentException("guestType must map to a host interface");
}
JavaConstant proxy = vmAccess.createHostProxy(hostObj, guestType);
Defensive patterns

Strategy: validation

Validate before calling

Class<?> hostClass = providers.getSnippetReflection().originalClass(guestType);
if (hostClass == null || !hostClass.isInterface()) {
    throw new IllegalArgumentException("guestType must map to a host interface: " + guestType);
}

Type guard

boolean proxyableGuestType(ResolvedJavaType t, SnippetReflectionProvider sr) {
    Class<?> c = sr.originalClass(t);
    return c != null && c.isInterface();
}

Prevention

When it happens

Trigger: Calling VMAccess.createHostProxy(hostTarget, guestType) where guestType has no original host class (foreign/unresolved type), or maps to a class rather than an interface (trying to proxy a concrete or abstract class). Note hostTarget itself is only null-checked; the failure is about guestType.

Common situations: Trying to expose a host object under a guest class (not interface); passing a ResolvedJavaType resolved by a different JVMCI runtime so originalClass returns null; guest types for annotation types or arrays which cannot be proxied.

Related errors


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