oracle/graal · error · EspressoClassLoadingException.ClassCircularityError

Class circularity detected

Error message

Class circularity detected

What it means

EspressoClassLoadingException.ClassCircularityError is thrown (with fixed message 'Class circularity detected') when class initialization or loading detects that a class is (transitively) its own superclass/superinterface, or a loading loop among classes. It mirrors the JVM's ClassCircularityError and is later converted to the guest error of the same name.

Source

Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EspressoClassLoadingException.java:42

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.espresso.classfile.descriptors.Symbol;
import com.oracle.truffle.espresso.classfile.descriptors.Type;
import com.oracle.truffle.espresso.classfile.descriptors.TypeSymbols;
import com.oracle.truffle.espresso.meta.Meta;
import com.oracle.truffle.espresso.runtime.EspressoException;
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;

/**
 * Indicates an exception that occurred during class loading.
 */
public abstract class EspressoClassLoadingException extends Exception {

    private static final long serialVersionUID = 1598679948708713831L;

    public static EspressoClassLoadingException.ClassCircularityError classCircularityError() throws EspressoClassLoadingException.ClassCircularityError {
        CompilerDirectives.transferToInterpreter();
        throw new EspressoClassLoadingException.ClassCircularityError("Class circularity detected");
    }

    public static EspressoClassLoadingException.IncompatibleClassChangeError incompatibleClassChangeError(String msg) throws EspressoClassLoadingException.IncompatibleClassChangeError {
        CompilerDirectives.transferToInterpreter();
        throw new EspressoClassLoadingException.IncompatibleClassChangeError(msg);
    }

    public static EspressoClassLoadingException.SecurityException securityException(String msg) throws EspressoClassLoadingException.SecurityException {
        CompilerDirectives.transferToInterpreter();
        throw new EspressoClassLoadingException.SecurityException(msg);
    }

    public static EspressoClassLoadingException.LinkageError linkageError(String msg) throws EspressoClassLoadingException.LinkageError {
        CompilerDirectives.transferToInterpreter();
        throw new EspressoClassLoadingException.LinkageError(msg);
    }

    public static EspressoClassLoadingException.IllegalAccessError illegalAccessError(String msg) throws EspressoClassLoadingException.IllegalAccessError {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Dump the class hierarchy of the involved classes (javap -v shows super/interfaces) and break the cycle.
  2. If classes were generated or transformed by your tooling, regenerate with consistent hierarchy metadata.
  3. If the input classes load fine on a standard JVM, file a GraalVM/Espresso issue with the reproducing jars.
  4. Retry with parallel class loading disabled / single-threaded context to rule out a race in the loading state machine.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    meta.loadKlass(type, definingLoader, StaticObject.NULL);
} catch (EspressoClassLoadingException.ClassCircularityError e) {
    // surface which class closed the cycle; the class set must be fixed, retrying will not help
}

Prevention

When it happens

Trigger: A guest class hierarchy where A extends B and B extends A, a class listed as its own superinterface, or initialization cycles detected during Espresso's load/resolve of the chain. Espresso invokes this factory from its class-loading state machine when the circularity invariant trips.

Common situations: Bytecode generators or hot-reload tools producing cyclic hierarchies; obfuscated or hand-crafted class files with self-referential super_class indices; bugs in Espresso's lazy loading order when loading heavily-interdependent classes in parallel.

Related errors


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