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
- Recompile the new class version with a lower bytecode target supported by the runtime (javac --release <supported-version>) and retry.
- Upgrade the GraalVM/Espresso runtime to a version that supports the class file version you need.
- 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
- Pin maven.compiler.release / javac --release to the runtime-supported version.
- Fail CI when artifacts contain class versions above the production runtime's cap.
- Upgrade GraalVM and guest JDK together, never independently.
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.