The JIT compiler

The Just-In-Time (JIT) compiler is a component of the runtime environment that improves the performance of Java™ applications by compiling bytecodes to native machine code at run time.

Java programs consists of classes, which contain platform-neutral bytecodes that can be interpreted by a JVM on many different computer architectures. At run time, the JVM loads the class files, determines the semantics of each individual bytecode, and performs the appropriate computation. The additional processor and memory usage during interpretation means that a Java application performs more slowly than a native application. The JIT compiler helps improve the performance of Java programs by compiling bytecodes into native machine code at run time.

The JIT compiler is enabled by default. When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting it. Theoretically, if compilation did not require processor time and memory usage, compiling every method could allow the speed of the Java program to match that of a native application.

JIT compilation does require processor time and memory usage. When the JVM first starts up, thousands of methods are called. Compiling all of these methods can significantly affect startup time, even if the program eventually achieves very good peak performance.

In practice, methods are not compiled the first time they are called. For each method, the JVM maintains an invocation count, which starts at a predefined compilation threshold value and is decremented every time the method is called. When the invocation count reaches zero, a just-in-time compilation for the method is triggered. Therefore, often-used methods are compiled soon after the JVM has started, and less-used methods are compiled much later, or not at all. The JIT compilation threshold helps the JVM start quickly and still have improved performance. The threshold value was selected to obtain an optimal balance between startup times and long-term performance.

The JIT compiler can compile a method at different optimization levels: cold, warm, hot, veryHot, or scorching (see optlevel in -Xjit). Higher optimization levels are expected to provide better performance, but they also have a higher compilation cost in terms of CPU and memory. The initial or default optimization level for a method is warm, but sometimes the JIT heuristics downgrade the optimization level to cold to improve startup time.

A method can be re-compiled to a higher optimization level through different mechanisms. One of these mechanisms is sampling: the JIT compiler maintains a dedicated sampling thread which wakes up periodically and determines which Java methods appear more often at the top of the stack. Such methods are deemed to be more important for performance, and they are candidates for being re-optimized at the higher levels of hot, veryHot, or scorching.

You can disable the JIT compiler, in which case the entire Java program will be interpreted. Disabling the JIT compiler is not recommended except to diagnose or work around JIT compilation problems.