oracle/graal · error · RedefinitionException

UnsupportedVersion

UnsupportedVersion

Error message

{}

What it means

RedefinitionException with RedefinitionError.UnsupportedVersion raised during hotswap when parsing the new class bytes throws ParserException.UnsupportedClassVersionError — the class file's major version is newer than what this Espresso runtime can read. The '{}' carries the parser's message (e.g. the unsupported major version number).

Source

Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java:237

            ClassChange classChange;
            DetectedChange detectedChange = new DetectedChange();
            StaticObject loader = klass.getDefiningClassLoader();
            TypeSymbols typeSymbols = klass.getContext().getTypes();
            try {
                parserKlass = ParserKlassProvider.parseKlassWithHostErrors(ClassRegistry.ClassDefinitionInfo.EMPTY, context.getClassLoadingEnv(), loader,
                                typeSymbols.fromClassNameEntry(hotSwapInfo.getName()), bytes);
                if (hotSwapInfo.isPatched()) {
                    byte[] patched = hotSwapInfo.getPatchedBytes();
                    newParserKlass = parserKlass;
                    // we detect changes against the patched bytecode
                    parserKlass = ParserKlassProvider.parseKlassWithHostErrors(ClassRegistry.ClassDefinitionInfo.EMPTY, context.getClassLoadingEnv(), loader,
                                    typeSymbols.fromClassNameEntry(hotSwapInfo.getNewName()),
                                    patched);
                }
            } catch (ValidationException | ParserException.ClassFormatError validationOrBadFormat) {
                throw new RedefinitionException(RedefinitionError.InvalidClassFormat, validationOrBadFormat.getMessage());
            } catch (ParserException.UnsupportedClassVersionError unsupportedClassVersionError) {
                throw new RedefinitionException(RedefinitionError.UnsupportedVersion, unsupportedClassVersionError.getMessage());
            } catch (ParserException.NoClassDefFoundError noClassDefFoundError) {
                // see HotSpot VM_RedefineClasses::load_new_class_versions
                throw new RedefinitionException(RedefinitionError.NamesDontMatch, noClassDefFoundError.getMessage());
            } catch (ParserException parserException) {
                throw EspressoError.shouldNotReachHere("Not a validation nor parser exception", parserException);
            }
            classChange = detectClassChanges(parserKlass, klass, detectedChange, newParserKlass, jvmtiRestrictions);
            if (classChange == ClassChange.CLASS_HIERARCHY_CHANGED && detectedChange.getSuperKlass() != null) {
                // keep track of unhandled changed super classes
                ObjectKlass superKlass = detectedChange.getSuperKlass();
                ObjectKlass oldSuperKlass = klass.getSuperKlass();
                ObjectKlass commonSuperKlass = (ObjectKlass) oldSuperKlass.findLeastCommonAncestor(superKlass);
                while (superKlass != commonSuperKlass) {
                    superClassChanges.add(superKlass);
                    superKlass = superKlass.getSuperKlass();
                }
            }
            ChangePacket packet = new ChangePacket(hotSwapInfo, newParserKlass != null ? newParserKlass : parserKlass, classChange, detectedChange);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Recompile the new class version with a lower bytecode target supported by the runtime (javac --release <supported-version>) and retry.
  2. Upgrade the GraalVM/Espresso runtime to a version that supports the class file version you need.
  3. Pin the project's maven.compiler.release / --release flag to the runtime-supported version so builds stay compatible.

Example fix

// before: compiled with JDK 21 -> major 65
<properties><maven.compiler.source>21</maven.compiler.source></properties>
// after: pin to the runtime's supported version
<properties><maven.compiler.release>17</maven.compiler.release></properties>
Defensive patterns

Strategy: validation

Validate before calling

// check the major version embedded in the bytes before redefining
int major = ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF);
if (major > MAX_SUPPORTED_MAJOR) {
    throw new IllegalArgumentException("class file major " + major + " exceeds supported " + MAX_SUPPORTED_MAJOR);
}

Try / catch

catch (RedefinitionException e) {
    if (e.getError() == RedefinitionError.UnsupportedVersion) { /* recompile with lower --release and retry once */ }
}

Prevention

When it happens

Trigger: Redefining a class with bytes compiled by a newer JDK than the Espresso runtime supports (e.g. class file major 65+ submitted to a runtime that caps below that); tools emitting --release flags targeting a newer bytecode level.

Common situations: Team members on different JDK versions: one compiles with JDK 21 while the GraalVM/Espresso runtime is 17-based; build systems whose target/release settings drifted after a JDK upgrade; CI producing artifacts with a newer default bytecode level than production.

Related errors


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