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

  1. 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).
  2. Update/reconfigure the bytecode instrumentation agent suspected of rewriting the method.
  3. 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

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


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/3064165b6dc7471e. Report an issue: GitHub.