Fundamentals 13 min read

Understanding Tiered Compilation in the JVM

This article explains the JVM's tiered compilation mechanism, detailing the client (C1) and server (C2) JIT compilers, the five compilation levels, code cache organization, relevant JVM flags, and demonstrates method compilation lifecycle through illustrative Java code examples and log analysis.

Cognitive Technology Team
Cognitive Technology Team
Cognitive Technology Team
Understanding Tiered Compilation in the JVM

The JVM executes bytecode by interpreting it and by using Just‑In‑Time (JIT) compilation to improve performance. Early Java versions required manual selection between two HotSpot JIT compilers: a client compiler for fast startup and a server compiler for overall throughput. Java 7 introduced tiered compilation, which combines both approaches.

JIT Compilers

C1 – Client Compiler optimizes for rapid startup, compiling code quickly with minimal analysis. Historically it was enabled with the -client flag, which is ignored on Java 8 and later.

C2 – Server Compiler focuses on long‑running applications, performing deeper analysis for better optimizations. It used the -server flag before Java 8.

Since Java 10, the Graal JIT compiler can be used as a C2 alternative, supporting both JIT and ahead‑of‑time modes.

Tiered Compilation

Tiered compilation introduces five compilation levels. Initially the JVM interprets all bytecode, gathers profiling data, and then uses C1 to compile hot methods quickly. When more profiling data is available, C2 recompiles those methods with aggressive optimizations. This yields fast startup (via C1) and high long‑term performance (via C2).

Benefits

More accurate profiling because compiled code continues to collect data.

Four‑fold increase in code‑cache usage, split into non‑method, profiled, and non‑profiled regions (configurable via -XX:NonNMethodCodeHeapSize , -XX:ProfiledCodeHeapSize , -XX:NonProfiledCodeHeapSize ).

Potential de‑optimization when optimistic assumptions prove wrong, causing the JVM to revert to interpretation.

Compilation Levels

Level 0 – Interpretation only.

Level 1 – Simple C1 compilation without profiling.

Level 2 – Limited C1 compilation with light analysis (used when the C2 queue is busy).

Level 3 – Full C1 compilation with complete analysis (default for most methods).

Level 4 – C2 compilation for maximum long‑term performance; after this level the JVM stops collecting profiling data for the method.

Compilation Parameters

Tiered compilation is enabled by default since Java 8. It can be disabled with -XX:-TieredCompilation . Specific levels can be forced, e.g., -XX:TieredStopAtLevel=1 to use only C1, or -Xint to run in pure interpretation mode.

Thresholds for when a method is promoted to a higher level are controlled by flags such as -XX:Tier4CompileThreshold=10000 . The default thresholds can be inspected with -XX:+PrintFlagsFinal .

Method Compilation Lifecycle (Example)

The following Java classes illustrate how methods move through the compilation levels. First, a JSON formatter:

public class JsonFormatter implements Formatter {
    private static final JsonMapper mapper = new JsonMapper();
    @Override
    public
String format(T object) throws JsonProcessingException {
        return mapper.writeValueAsString(object);
    }
}

Then an XML formatter:

public class XmlFormatter implements Formatter {
    private static final XmlMapper mapper = new XmlMapper();
    @Override
    public
String format(T object) throws JsonProcessingException {
        return mapper.writeValueAsString(object);
    }
}

And a driver class that switches between the two implementations:

public class TieredCompilation {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 1_000_000; i++) {
            Formatter formatter;
            if (i < 500_000) {
                formatter = new JsonFormatter();
            } else {
                formatter = new XmlFormatter();
            }
            formatter.format(new Article("Tiered Compilation in JVM", "Baeldung"));
        }
    }
}

Running the program with -XX:+PrintCompilation produces logs that show the transition from interpretation (level 0) to C1 (level 3) and later to C2 (level 4). Sample log excerpts illustrate compilation, re‑compilation, and de‑optimization events.

Conclusion

The article explored JVM tiered compilation, covering the two JIT compilers, the five compilation levels, JVM flags for tuning, and a practical example that visualizes the method‑compilation lifecycle via compilation logs.

JavaJVMperformanceJITCode CacheCompilation LevelsTiered Compilation
Cognitive Technology Team
Written by

Cognitive Technology Team

Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.