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
- Pass a ResolvedJavaType that resolves to a host interface: verify originalClass(type) != null && originalClass(type).isInterface() before calling
- Extract an interface for the host object's API and use that interface type as guestType
- 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
- Model interop boundaries with interfaces, never classes
- Validate guestType at API design time: document it must be an interface type
- Ensure guest types are resolved by the same runtime that builds the proxy
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
- ${input} is not an instance of a registered class.
- Method ${methodName} not found
- Element {} should be a {}, got {}
- Element {} should be an object, got {}
- Expected an array constant, got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/723288cb9661a231.
Report an issue: GitHub.