Tuesday, March 09, 2021

JIT Compiler

Lets start by talking a bit about JIT compiler...

This is an age old topic that has been widely discussed. There are a lot of materials out there explaining JIT compilation in much greater detail.

But I am bent on telling it one more time... the way I have understood it... put in as simply as I can!!!

So lets start with this universal Hello World! code

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

To execute this program, we execute two commands

  1. javac command to compile this source code into a class file
  2. java command to execute the class file
javac Main.java

java Main

The first command converts the source code into set of JVM instructions, commonly referred to as Java byte codes. These byte codes are stored in a .class file.

The second command starts a JVM instance, reads the byte codes from the class file and executes them on the JVM to produce the desired output.  

Now the JVM itself is a virtual layer on top of the hardware on which we execute the java command. What JVM actually does is interpret the byte codes and convert it (compile it) into assembly language instruction set that can be executed on the specific hardware.  

So the JVM, at a high level performs the following steps for each byte code instruction

  1. Read that byte code instruction
  2. Interpret that byte code and compile it to generate the equivalent assembly language instructions for the specific hardware on which its getting executed 
  3. And finally get these generated assembly language instructions executed on that hardware

This might just be fine for a simple program like hello world, but the real world programs are much more complex. 

Consider for instance, the below example where we print the String "Hello World" from within the method hello(). This method is called 10,000 times over from the main method

public class Main1 {

    public static void main(String[] args) {

        for (int i = 0; i < 10000; i++) {
            hello();
        }
    }
    
    static void hello() {
        System.out.println("Hello World!");
    }
}

The JVM performing the cycle of read -> interpret -> execute 10,000 times would sure be not an efficient approach. 

The compiled instruction set that gets generated is going to be the same for each of the 10,000 cycles. Java byte code need not be interpreted each time the JVM loops through. 

The component that does this compilation is the Just In-time Compiler or the JIT compiler and it is executed as part of the JVM process. 

So, 

  • javac is the static compiler that converts java source files into byte code instruction set
  • JIT compiler is part of the JVM process that is started by the java command and it performs dynamic compilation of byte code instruction set to native assembly language instructions


No comments:

Post a Comment