oracle/graal · error · RuntimeException
Error disassembling %s%nPartial disassembly:%n%s
Error message
Error disassembling %s%nPartial disassembly:%n%s
What it means
BytecodeDisassembler.disassemble wraps its whole decoding loop in a try/catch (Throwable) and rethrows a RuntimeException carrying the method descriptor plus the partial disassembly produced so far. Any failure while decoding an instruction or resolving a constant-pool operand (index out of range, unsupported opcode, malformed CP entry) is reported this way, with the original cause chained.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java:252
buf.append(String.format("%4d: %-14s", bci, mnemonic));
} else {
buf.append(bci).append(' ').append(mnemonic);
}
if (stream.nextBCI() > bci + 1) {
if (!format) {
buf.append(' ');
}
decodeOperand(buf, stream, cp, method, bci, opcode);
}
if (newLine != null) {
buf.append(newLine);
}
}
stream.next();
opcode = stream.currentBC();
}
} catch (Throwable e) {
throw new RuntimeException(String.format("Error disassembling %s%nPartial disassembly:%n%s", method.format("%H.%n(%p)"), buf.toString()), e);
}
return buf.toString();
}
private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPool cp, ResolvedJavaMethod method, int bci, int opcode) {
// @formatter:off
switch (opcode) {
case BIPUSH : buf.append(stream.readByte()); break;
case SIPUSH : buf.append(stream.readShort()); break;
case NEW :
case CHECKCAST :
case INSTANCEOF :
case ANEWARRAY : {
int cpi = stream.readCPI();
JavaType type = cp.lookupType(cpi, opcode);
cpi = cpiFunction.apply(opcode, cpi);
if (format) {
buf.append(String.format("#%-10d // %s", cpi, type.toJavaName()));View on GitHub (pinned to a66e9ccd1d)
Solutions
- Read the chained cause (e.getCause()) — it names the actual decoding failure (e.g. ConstantPoolError, IndexOutOfBounds) and points at the failing instruction.
- Disassemble the same class with javap -c or javap -v to confirm whether the class file itself is malformed; if javap also fails, the producer (obfuscator/agent) is at fault.
- If javap succeeds, report a Graal issue with the method descriptor and partial disassembly from the message.
- Upgrade Graal to a version matching the JDK's bytecode level if the class uses recently introduced instructions.
Defensive patterns
Strategy: try-catch
Try / catch
try {
String dis = new BytecodeDisassembler().disassemble(method);
} catch (RuntimeException e) {
if (e.getCause() != null) {
LOG.warn("Disassembly failed at cause: {}", e.getCause());
}
// fall back to javap-style output or skip
} Prevention
- Treat disassembly as best-effort tooling: never let its failure fail a compilation or production path.
- Pre-validate class files with a bytecode checker (ASM CheckClassAdapter) before disassembling untrusted input.
When it happens
Trigger: Calling disassemble(method) on a ResolvedJavaMethod whose bytecode or constant pool is malformed or unexpected: bad CPI indices in operands, a tool (obfuscator/instrumentation agent) writing non-standard bytecode, or a disassembler gap for a newly added JVM instruction. The partial buffer in the message shows decoding progressed up to the failing BCI.
Common situations: Dumping bytecode during Graal debugging (-Dgraal.Dump triggers disassembly), disassembling classes processed by coverage tools, obfuscators, or ASM-based agents, or running a Graal build older than the JDK that produced the class files (new bytecodes). Frequently co-occurs with error 21's bridge scanning, which disassembles bridges.
Related errors
- multiline cannot be true when newLine is null
- Couldn't find method bridged by %s:%n%s
- No opcode for %s
- Could not connect to the IGV on %s:%d
- Failed to open %s to dump IGV graphs
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/e3310098de3529c1.
Report an issue: GitHub.