oracle/graal · critical · ForceDeoptSpeculationPhase.TooManyDeoptimizationsError
too many decompiles: {} {}
Error message
too many decompiles: {} {} What it means
Before (re)compiling a method, CompilationTask.performRecompilationCheck verifies that the method's deoptimization count has reached MethodRecompilationLimit; if so it throws ForceDeoptSpeculationPhase.TooManyDeoptimizationsError with the decompile count and a deopt summary. This aborts a pathological compile/deoptimize cycle instead of looping forever.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java:395
}
ListIterator<BasePhase<? super LowTierContext>> lowTierPhasesIterator = suites.getLowTier().findPhase(SchedulePhase.FinalSchedulePhase.class);
if (lowTierPhasesIterator != null) {
lowTierPhasesIterator.previous();
lowTierPhasesIterator.add(new ForceDeoptSpeculationPhase(decompileCount));
}
}
}
/**
* Checks whether the recompilation limit is exceeded, and if so, throws an exception.
*
* @param options the option values
* @param method the compiled method
*/
private void performRecompilationCheck(OptionValues options, HotSpotResolvedJavaMethod method) {
if (checkRecompileCycle && (MethodRecompilationLimit.getValue(options) >= 0 && decompileCount >= MethodRecompilationLimit.getValue(options))) {
ProfilingInfo info = profileProvider.getProfilingInfo(null, method);
throw new ForceDeoptSpeculationPhase.TooManyDeoptimizationsError("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase.getDeoptSummary(info));
}
}
private static final TimerKey CompilationReplayTime = DebugContext.timer("CompilationReplayTime").doc("The time spent in recorded/replayed compilations.");
private static final CounterKey CompilationReplayBytecodes = DebugContext.counter("CompilationReplayBytecodes").doc("The size of bytecodes compiled in recorded/replayed compilations.");
/**
* Performs a recorded or replayed compilation.
*
* @param initialDebug the initial debug context
* @return the compilation result
*/
@SuppressWarnings("try")
private HotSpotCompilationRequestResult performCompilationWithReplaySupport(DebugContext initialDebug) {
OptionValues options = initialDebug.getOptions();
HotSpotGraalCompiler selectedCompiler;
if (compiler.getGraalRuntime().getReplayCompilationSupport() != null) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Inspect the deopt summary in the message to find which speculation/deopt reason loops, and fix the root cause (e.g. stabilizing profiles or fixing the custom phase/speculation)
- Raise or disable the guard for diagnosis: -Dgraal.MethodRecompilationLimit=-1 (or a larger value)
- Report the reproducer to the Graal team if it occurs with a stock configuration on unmodified code
Example fix
# before java -XX:+UseJVMCICompiler MyApp # TooManyDeoptimizationsError: too many decompiles: 5 ... # after (diagnosis: raise the limit while investigating the deopt loop) java -XX:+UseJVMCICompiler -Dgraal.MethodRecompilationLimit=-1 MyApp # then use -Dgraal.Dump=... and the deopt summary to find the unstable speculation
Defensive patterns
Strategy: fallback
Try / catch
// usually not caught: TooManyDeoptimizationsError is a Graal-internal Error surfaced via a crashed compilation; treat as a bug report trigger, not a recoverable path
Prevention
- Keep MethodRecompilationLimit at defaults; only raise it for diagnosis
- Watch for repeated deopt+recompile of the same method in logs before it hits the limit
- Avoid unstable custom speculation/profile injection in plugins
When it happens
Trigger: Running with checkRecompilationCycle enabled and MethodRecompilationLimit >= 0 (it is on by default with a finite limit), when a method's accumulated decompiles (decompileCount) >= the limit at the start of a compilation; the summary comes from profileProvider.getProfilingInfo(null, method) for the failing method.
Common situations: Degenerate profiling feedback or unstable speculation causing the method to deopt and recompile repeatedly (e.g. flipping branch profiles in benchmarks, broken custom speculation plugins); lowering MethodRecompilationLimit too far; class redefinition (instrumentation) churn.
Related errors
- Compiler configuration '%s' not found. Available configurati
- %s garbage collector is not supported by Graal
- Multiple garbage collectors selected: %s %s
- Graph was permanetly frozen.
- unknown verbosity:
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/c021255f0a099426.
Report an issue: GitHub.