oracle/graal · error · RedefinitionException
NamesDontMatch
NamesDontMatch
Error message
{} What it means
RedefinitionException with RedefinitionError.NamesDontMatch thrown when parsing the replacement class bytes triggers ParserException.NoClassDefFoundError. Following HotSpot's VM_RedefineClasses::load_new_class_versions semantics, a class referenced during parsing (typically a superclass or interface of the new version) could not be found, which surfaces as a names-do-not-match failure. The '{}' is the underlying parser message naming the missing dependency.
Source
Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java:240
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);
result.add(packet);
temp.put(klass, packet);
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Ensure the replacement bytes define exactly the same class name as the class being redefined (no renames).
- Deploy/load every new superclass or interface referenced by the replacement class before triggering the redefinition.
- Check the exception message for the missing type name and add that dependency to the runtime classpath.
- If the rename is intentional, use class retransformation with a compatible toolchain or restart the context instead of hotswap.
Example fix
// before: bytes define com.example.NewName but redefining com.example.OldName redefine(oldNameKlass, new nameBytes); // after: keep the class name identical in the replacement bytes redefine(oldNameKlass, sameNameBytes); // bytes must declare com.example.OldName
Defensive patterns
Strategy: validation
Validate before calling
// verify the bytes define the same class you are redefining
String defined = new org.objectweb.asm.ClassReader(bytes).getClassName();
if (!defined.equals(klass.getType().toString().replace('/', '.'))) {
throw new IllegalArgumentException("bytes define " + defined + ", expected " + klass.getName());
}
// also ensure any new supertype is loadable by the defining loader
for (String supertype : collectSupertypes(bytes)) {
Class.forName(supertype, false, hostLoaderFor(klass));
} Try / catch
catch (RedefinitionException e) {
if (e.getError() == RedefinitionError.NamesDontMatch) { /* deploy missing dependency or fix class name, then retry */ }
} Prevention
- Never rename classes that participate in hotswap.
- Deploy new supertypes before the classes that reference them.
- Log the missing-type message; it names exactly what failed to load.
When it happens
Trigger: Submitting hotswap bytes for class A whose new version references a superclass/interface (or the class name itself differs from the class being redefined) that is not loadable by the defining class loader; redefining a class with bytes compiled from a renamed source file.
Common situations: Refactoring that renames a class while a hotswap tool still submits old/new name pairs; adding an interface or superclass in the new version that is not on the runtime classpath; multi-module builds where the dependency containing the new supertype was not deployed before the swap.
Related errors
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1423c86992a41d4b.
Report an issue: GitHub.