oracle/graal · error · PermanentBailoutException
Unbalanced monitor enter-exit in OSR compilation with locks:
Error message
Unbalanced monitor enter-exit in OSR compilation with locks:
What it means
PermanentBailoutException thrown when VerifyLockDepthPhase, run after OnStackReplacementPhase re-inserts monitor enters for the OSR entry, reports a LockStructureError. The error message is prefixed with 'Unbalanced monitor enter-exit in OSR compilation with locks: ' and describes the exact lock-depth violation. It means the reconstructed lock ordering at the OSR entry would not match the interpreter's monitor stack, so compiled code could not legally acquire/release the monitors.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/phases/OnStackReplacementPhase.java:237
OsrWithLocksCount.increment(debug);
try (DebugCloseable context = osrStart.withNodeSourcePosition()) {
for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
MonitorIdNode id = osrState.monitorIdAt(i);
ValueNode lockedObject = osrState.lockAt(i);
OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
osrMonitorEnter.setStateAfter(osrStart.stateAfter());
FixedNode oldNext = osrStart.next();
oldNext.replaceAtPredecessor(null);
osrMonitorEnter.setNext(oldNext);
osrStart.setNext(osrMonitorEnter);
}
}
debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
try {
new VerifyLockDepthPhase().run(graph);
} catch (VerifyLockDepthPhase.LockStructureError e) {
throw new PermanentBailoutException("Unbalanced monitor enter-exit in OSR compilation with locks: " + e.getMessage());
}
}
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result");
new DeadCodeEliminationPhase(Required).apply(graph);
/*
* There must not be any parameter nodes left after OSR compilation.
*/
assert graph.getNodes(ParameterNode.TYPE).count() == 0 : "OSR Compilation contains references to parameters.";
}
/**
* Generates a speculative type check on {@code osrLocal} for {@code narrowedStamp}.
*
* @return a {@link PiNode} that narrows the type of {@code osrLocal} to {@code narrowedStamp}
*/
private static ValueNode narrowOsrLocal(StructuredGraph graph, Stamp narrowedStamp, ValueNode osrLocal, SpeculationReason reason,
OSRStartNode osrStart, EntryProxyNode proxy, FrameState osrState) {
View on GitHub (pinned to a66e9ccd1d)
Solutions
- No JVM action needed: the bailout is safe; HotSpot continues interpreting the method.
- Simplify the synchronization structure around the hot loop (hoist synchronized out of the loop) to make OSR+locks verifiable.
- Compiler developers: reproduce with -Dgraal.Dump=:2 and inspect 'After inserting OSR monitor enters' to see which path breaks lock-depth balance.
Defensive patterns
Strategy: fallback
Try / catch
try {
compileResult = compile(task);
} catch (PermanentBailoutException e) {
if (e.getMessage().startsWith("Unbalanced monitor enter-exit")) {
// safe fallback: interpreter continues; log and move on
}
} Prevention
- Keep monitor nesting shallow and unconditional around hot loops.
- Report recurring OSR-lock bails with graal dumps attached so the compiler team can fix the shape.
When it happens
Trigger: OSR compilation of a method with monitors where re-materializing monitorenter nodes at OSR start yields a lock depth that does not return to zero or mismatches per exception path — typically nested/conditional synchronization on the OSR path with SupportOSRWithLocks enabled.
Common situations: Complex synchronized control flow (locks acquired conditionally inside the loop, nested monitors, try/finally around monitorexit) hitting OSR; usually not actionable by end users — it is a compiler limitation that safely falls back to the interpreter.
Related errors
- OSR with locks disabled.
- OSR compilation without OSR entry loop.
- OSR with stack entries not supported: %s
- Can not duplicate block with JSR data
- Too many loops in method
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/586708bbe7d194dd.
Report an issue: GitHub.