oracle/graal · error · PermanentBailoutException
Block that is reached by a fall through end of code is reach
Error message
Block that is reached by a fall through end of code is reached.
What it means
Thrown by BytecodeParser.processBlock when the block being parsed is marked isOutOfBounds — a block whose bytecode range lies outside the method's declared code array (reached by falling through the end of the code). The JVM verifier rejects such flow, so Graal permanently bails out instead of building a graph for malformed bytecode.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java:3681
private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) {
if (target.isStatic()) {
return appendConstant(getConstantReflection().asJavaClass(target.getDeclaringClass()));
} else {
return state.loadLocal(0, JavaKind.Object);
}
}
@SuppressWarnings("try")
protected void processBlock(BciBlock block) {
// Ignore blocks that have no predecessors by the time their bytecodes are parsed
FixedWithNextNode firstInstruction = getFirstInstruction(block);
if (firstInstruction == null) {
debug.log("Ignoring block %s", block);
return;
}
if (block.isOutOfBounds()) {
throw new PermanentBailoutException("Block that is reached by a fall through end of code is reached.");
}
try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader())) {
lastInstr = firstInstruction;
frameState = getEntryState(block);
currentBlock = block;
if (firstInstruction instanceof AbstractMergeNode) {
setMergeStateAfter(block, firstInstruction);
}
if (block == blockMap.getUnwindBlock()) {
handleUnwindBlock();
} else if (block instanceof ExceptionDispatchBlock) {
createExceptionDispatch((ExceptionDispatchBlock) block);
} else {
handleBytecodeBlock(block);
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Regenerate or fix the class file so no branch targets beyond code_length (verify with the JVM: `java -Xverify:all` or a bytecode verifier tool).
- Update/reconfigure the bytecode instrumentation agent suspected of rewriting the method.
- Rebuild/re-download the artifact to rule out corrupted class data.
Defensive patterns
Strategy: validation
Validate before calling
// verify the class before JIT-heavy runs // javap -c Myкласс.class -> ensure no branch target >= code_length // or run: java -Xverify:all ...
Prevention
- Run with strict verification (`-Xverify:all`) in CI for generated classes.
- Test bytecode-transforming agents against Graal-enabled JVMs before shipping.
When it happens
Trigger: processBlock(block) with block.isOutOfBounds() true: control flow reaches a block whose start BCI is at/after the end of the bytecode array, i.e. a branch target or fall-through computed beyond code_length.
Common situations: Malformed or corrupted class files; bytecode rewritten late by instrumentation agents (ASM/AspectJ/coverage tools) that adjust jump offsets incorrectly; hand-generated bytecode with wrong branch destinations; class files truncated by a broken download or class-data-sharing issue.
Related errors
- Can not duplicate block with JSR data
- Too many loops in method
- Irreducible
- Non-reducible loop requires too much duplication. Setting %s
- cannot link call from %s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/3064165b6dc7471e.
Report an issue: GitHub.