Many folks were asking me about the Just In Time(aka JIT) heuristics after reading my One Java Two Compilers post

The basic thing that the JIT does is deciding weather a specific portion of the code should get compiled or get executed by the interpreter.

The portions that better get compiled called hotspots“Once the  … optimizer has gathered information during execution about program hot spots, it not only compiles the hot spot into native code”

The JIT has to consider what would be faster, notice that compiling a hot spot takes time, running code line by line is faster than compiling it and execute the compiled native-code, yet in case the code will be called many times in the future, getting the compiled native code out of the cache and execute it is faster than interpreting it

The JIT select hotspots to be compiled based on the prediction of how often they are likely to be called during the rest of the program’s execution.

This prediction is usually done by taking into account two major factors (1) the size of the code (2) the so-far execution statistics

Moreover: upon compiling, the JIT might optimize the code, those optimization’s sometime proven to be wrong and even cause internal JVM errors which get fixed by going back to the beginning of the hotspot and interpreting it line by line (while removing the erroneous compiled code from the memory).

You probably figure by now that the JVM is taking sophisticated statics while running.

Here is a list of possible optimization’s:

  1.  Inline, replacing method call with the code of the called method
  2. Eliminating null-verification’s (e.g. removing “if(x!=null)”)
  3. Stack-allocation (I learned this cool feature about a week ago): JIT tries to identify local variables that are almost surely local to a specific method and allocate them on the stack instead of the heap, this way the GC works faster as it has less garbage to clean..
  4. Solving polymorphic calls, instead of using a virtual table, the JIT perdict which type of object is referencing at.
  5. Array range check, when iterating an array, instead of checking for each index if it’s in the approved range of the array, it check only the first and last indices <- this makes numeric calculations run faster

Extra reading:


One Java, Two compilers..

Lately I was discussing Java with few students of mine..

It seems like that for students there is a lot of confusion regarding how Java/The JVM works because there are TWO compilers involve, so when someone mentions a compiler or the Just In Time compiler some of them would imagine it’s the same one, the Java Compiler..

So how does it really works?

It’s simple..

1) You write Java code ( which compiles to “bytecode“, this is done using the javacthe 1st compiler.

It’s well known fact that Java can be written once get compiled and run anywhere (on any platform) which mean that different types of JVM can get installed over any type of platform and read the same good old byte code

2) Upon execution of a Java program (the class file or Jar file that consists of some classes and other resources) the JVM should somehow execute the program and somehow translate it to the specific platform machine code.

In the first versions of Java, the JVM was a “stupid” interprater that executes byte-code line by line….that was extremely slow…people got mad, there were a lot of “lame-java, awesome c” talks…and the JVM guys got irratated and reinvented the JVM.

the “new” JVM initially was available as an add-on for Java 1.2 later it became the default Sun JVM (1.3+).

So what did they do? they added a second compiler.. Just In Time compiler(aka JIT)..

Instead of interpreting line by line, the JIT compiler compiles the byte-code to machine-code right after the execution..

Moreover, the JVM is getting smarter upon every release, it “knows” when it should interpat the code line-by-line and what parts of the code should get compiled beforehand (still on runtime).

It does that by taking real-usage statistics, and a long-list of super-awesome heuristics..

The JVM can get configured by the user in order to disable/enable some of those heuristics..

To summarize, In order to execute java code, you use two different compilers, the first one(javac) is generic and compiles java to bytecode, the second(jit) is platform-dependent and compiles some portions of the bytecode to machine-code in runtime!