oracle/graal · error · PermanentBailoutException

OSR with locks disabled.

Error message

OSR with locks disabled.

What it means

PermanentBailoutException thrown when an OSR compilation contains monitors (synchronized blocks on the OSR path) but the SupportOSRWithLocks option is disabled. OSR with locks requires reconstructing monitor state at the OSR entry, a feature gated behind an option; when off, Graal permanently bails out rather than emit incorrect lock state.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/phases/OnStackReplacementPhase.java:143

            return;
        }
        debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());

        final EntryMarkerNode originalOSRNode = getEntryMarker(graph);
        final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode, providers);
        final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode);

        if (originalOSRLoop == null) {
            /*
             * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we
             * cannot decide where to deopt and which framestate will be used. In the worst case the
             * framestate of the OSR entry would be used.
             */
            throw new PermanentBailoutException("OSR compilation without OSR entry loop.");
        }

        if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) {
            throw new PermanentBailoutException("OSR with locks disabled.");
        }

        EntryMarkerNode osr = OnStackReplacementUtils.peelEntryLoops(graph, providers.getLoopsDataProvider(), () -> getEntryMarker(graph), loop -> {
        },
                        (iterations, maxIterations) -> {
                            throw GraalError.shouldNotReachHere(iterations + " " + maxIterations); // ExcludeFromJacocoGeneratedReport
                        }, "OnStackReplacement loop peeling result");

        StartNode start = graph.start();
        FrameState osrState = osr.stateAfter();
        OSRStartNode osrStart;
        try (DebugCloseable context = osr.withNodeSourcePosition()) {
            osr.setStateAfter(null);
            osrStart = graph.add(new OSRStartNode());
            FixedNode next = osr.next();
            osr.setNext(null);
            osrStart.setNext(next);
            graph.setStart(osrStart);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Enable the feature: -Dgraal.SupportOSRWithLocks=true.
  2. Refactor the hot loop out of the synchronized region so OSR sees no monitors.
  3. Accept the bailout (interpretation continues) if OSR of that method is not performance-critical.

Example fix

# before
-XX:+UseJVMCICompiler  # SupportOSRWithLocks defaults off
# PermanentBailoutException: OSR with locks disabled.

# after
-XX:+UseJVMCICompiler -Dgraal.SupportOSRWithLocks=true
Defensive patterns

Strategy: validation

Validate before calling

// Before enabling Graal on workloads with synchronized hot loops
boolean needsOsrLocks = workloadHasSynchronizedLoops;
boolean osrLocksEnabled = Boolean.parseBoolean(System.getProperty("graal.SupportOSRWithLocks", "false"));
if (needsOsrLocks && !osrLocksEnabled) {
    System.setProperty("graal.SupportOSRWithLocks", "true");
}

Try / catch

try {
    // run workload under JVMCI
} catch (PermanentBailoutException e) {
    if ("OSR with locks disabled.".equals(e.getMessage())) {
        // relaunch with -Dgraal.SupportOSRWithLocks=true
    }
}

Prevention

When it happens

Trigger: OSR-compiling a method with a synchronized loop (or a loop containing monitorenter/monitorexit) while -Dgraal.SupportOSRWithLocks=false (its default in some configurations). osrWithLocks(entryMarker) reports the monitors and the option check fails.

Common situations: Benchmarks with synchronized hot loops running on configurations where OSR+locks support is disabled; explicitly turning the option off for determinism; older compiler builds where the feature was immature.

Related errors


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