oracle/graal · error · ClassFormatError
Invalid constant pool tag: %s
Error message
Invalid constant pool tag: %s
What it means
ClassfileConstantPool parses the constant pool tag-by-tag; the JVMS defines a closed set of tags, and the default branch throws ClassFormatError('Invalid constant pool tag') for any tag byte outside it. This indicates malformed class-file data, not a usage error.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java:135
return new ClassfileConstant.Primitive(tag, JavaConstant.forDouble(stream.readDouble()));
case ClassfileConstant.CONSTANT_NameAndType:
return new ClassfileConstant.NameAndType(stream);
case ClassfileConstant.CONSTANT_Utf8:
return new ClassfileConstant.Utf8(stream.readUTF());
case ClassfileConstant.CONSTANT_MethodHandle:
skipFully(stream, 3); // reference_kind, reference_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodHandle_info");
case ClassfileConstant.CONSTANT_MethodType:
skipFully(stream, 2); // descriptor_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodType_info");
case ClassfileConstant.CONSTANT_Dynamic:
skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_Dynamic_info");
case ClassfileConstant.CONSTANT_InvokeDynamic:
skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_InvokeDynamic_info");
default:
throw new ClassFormatError("Invalid constant pool tag: " + tag);
}
}
@Override
public int length() {
return entries.length;
}
<T extends ClassfileConstant> T get(Class<T> c, int index) {
return c.cast(entries[index]);
}
@Override
public void loadReferencedType(int index, int opcode) {
if (opcode == Bytecodes.INVOKEDYNAMIC) {
throw new GraalError("INVOKEDYNAMIC not supported by " + ClassfileBytecodeProvider.class.getSimpleName());
}
entries[index].loadReferencedType(this, index, opcode);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Reproduce the parse outside Graal with javap -v on the class to confirm the file is malformed.
- Rebuild or re-download the jar containing the broken class.
- If you generate classes with ASM/bytecode tooling, verify the writer version and output with a verifier (e.g. CheckClassAdapter).
Defensive patterns
Strategy: try-catch
Try / catch
try {
ClassfileConstantPool pool = new ClassfileConstantPool(stream, context);
} catch (ClassFormatError e) {
// Malformed bytes: quarantine the artifact and rebuild/re-download it; never parse it again as-is
throw new IllegalStateException("Corrupt class data for " + type.toJavaName(), e);
} Prevention
- Verify downloaded jars (checksums/signatures) before feeding classes to the parser.
- If you generate bytecode, run it through a verifier (ASM CheckClassAdapter) in tests.
When it happens
Trigger: The DataInputStream points at data that is not a well-formed constant pool: corrupt class bytes, a non-class resource misinterpreted as a class, or a class mutated by broken bytecode tooling.
Common situations: Corrupted jars (failed download, disk issue), bytecode generators computing wrong constant pool offsets, class files processed by an obfuscator/agent bug.
Related errors
- Unexpected tag: ${tag}
- Error disassembling %s%nPartial disassembly:%n%s
- Invalid constant pool index :
- unknown klass type :
- unknown pool type
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/a115ddfed5660233.
Report an issue: GitHub.