oracle/graal · error · IllegalArgumentException

${input} is not an instance of a registered class.

Error message

${input} is not an instance of a registered class.

What it means

Thrown by RecordingCompilationProxies.proxify when replay-compilation recording is asked to wrap an object whose class was never registered in CompilerInterfaceDeclarations. The recording machinery can only intercept calls on interfaces it knows how to proxy; an unregistered concrete class cannot be proxied, so it fails fast with IllegalArgumentException instead of silently recording nothing.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java:171

    @Override
    public Platform targetPlatform() {
        return Platform.ofCurrentHost();
    }

    @Override
    public DebugCloseable withDebugContext(DebugContext debugContext) {
        return DebugCloseable.VOID_CLOSEABLE;
    }

    @Override
    public CompilationProxy proxify(Object input) {
        if (input instanceof CompilationProxy compilationProxy) {
            return compilationProxy;
        }
        CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input);
        if (registration == null) {
            throw new IllegalArgumentException(input + " is not an instance of a registered class.");
        }
        return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> {
            if (method.equals(CompilationProxyBase.unproxifyMethod)) {
                return input;
            }
            Object[] unproxifiedArgs = (Object[]) unproxifyRecursive(args);
            CompilerInterfaceDeclarations.MethodStrategy methodStrategy = registration.findStrategy(method);
            OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(input, method, unproxifiedArgs);
            Object result;
            if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) {
                Object resultOrMarker = recorder.getRecordedResultOrMarker(key);
                if (resultOrMarker instanceof SpecialResultMarker.ExceptionThrownMarker exceptionThrownMarker) {
                    throw (Throwable) proxifyRecursive(exceptionThrownMarker.getThrown());
                } else if (resultOrMarker == SpecialResultMarker.NULL_RESULT_MARKER) {
                    return null;
                } else if (resultOrMarker != SpecialResultMarker.NO_RESULT_MARKER) {
                    return proxifyRecursive(resultOrMarker);
                }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Register the object's class/interface in CompilerInterfaceDeclarations so findRegistrationForInstance returns non-null, then retry the recording.
  2. If the object should pass through unproxied, check it for CompilationProxy before calling proxify or route it outside the proxy layer.
  3. Update to a GraalVM version where the class is registered (if the class comes from a newer compiler-interface change).

Example fix

// before
Object proxy = recordingProxies.proxify(newObject);

// after
CompilerInterfaceDeclarations.Registration reg = declarations.findRegistrationForInstance(newObject);
if (reg == null) {
    // register newObject's interface in CompilerInterfaceDeclarations first
    throw new IllegalStateException("Register " + newObject.getClass() + " before recording");
}
Object proxy = recordingProxies.proxify(newObject);
Defensive patterns

Strategy: validation

Validate before calling

// before proxify, confirm the instance is registrable
Object input = /* ... */;
if (!(input instanceof CompilationProxy) &&
    declarations.findRegistrationForInstance(input) == null) {
    // do not call proxify; register the class or pass the raw object
    throw new IllegalStateException("Unregistered class for recording: " + input.getClass());
}
CompilationProxy proxy = recordingProxies.proxify(input);

Prevention

When it happens

Trigger: Calling RecordingCompilationProxies.proxify(Object) with an input that is neither already a CompilationProxy nor an instance of a class registered via CompilerInterfaceDeclarations registration lookup (declarations.findRegistrationForInstance(input) returns null). Typically happens when a new type flows through the compiler interface during -Dgraal.ReplayCompilation recording but its interface was not added to the registered declarations.

Common situations: Extending the compiler-interface surface (adding a new implementation class of jdk.vm.ci or Graal interface types) without registering it in CompilerInterfaceDeclarations; version mismatches where a replay/recording branch added a class the declarations table does not know; recording a compilation that touches a rarely used VM-CI implementation class.

Related errors


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