gives Java the platform independence of an interpreted language. Because it is executing an
idealized binary code, the java program is able to compile the code into the platform binary
as the code executes. This compilation occurs as the program is executed: it happens “just in
The manner in which the Java Virtual Machine compiles this code as it executes is the focus
of this chapter.
Hot Spot Compilation
As discussed in Chapter 1 , the Java implementation discussed in this topic is Oracle's HotS-
pot JVM. This name (HotSpot) comes from the approach it takes toward compiling the code.
In a typical program, only a small subset of code is executed frequently, and the performance
of an application depends primarily on how fast those sections of code are executed. These
critical sections are known as the hot spots of the application; the more the section of code is
executed, the hotter that section is said to be.
Hence, when the JVM executes code, it does not begin compiling the code immediately.
There are two basic reasons for this. First, if the code is going to be executed only once, then
compiling it is essentially a wasted effort; it will be faster to interpret the Java bytecodes than
to compile them and execute (only once) the compiled code.
But if the code in question is a frequently called method, or a loop that runs many iterations,
then compiling it is worthwhile: the cycles it takes to compile the code will be outweighed
by the savings in multiple executions of the faster compiled code. That trade-off is one reas-
on that the compiler executes the interpreted code first—the compiler can figure out which
methods are called frequently enough to warrant their compilation.
The second reason is one of optimization: the more times that the JVM executes a particular
method or loop, the more information it has about that code. This allows the JVM to make a
number of optimizations when it compiles the code.
A number of those optimizations (and ways to affect them) are discussed later in this chapter,
but for a simple example, consider the case of the equals() method. This method exists in
every Java object (since it is inherited from the Object class) and is often overridden. When
the interpreter encounters the statement b = obj1.equals(obj2) , it must look up the type
(class) of obj1 in order to know which equals() method to execute. This dynamic lookup
can be somewhat time-consuming.