JIT in Java
What is JIT ?
JIT stands for " Just in Time Compiler ". It is called "Just in time" because it is called at the very last moment when the interpretation is going to happen. So, before the interpreter, the JIT compiler quickly analyses the code and removes redundancy so that the interpretation can happen faster. It is one of the most confusing topics for developers. JIT is a part of JVM ( Java virtual machine). The actual purpose of JIT is to compile bytecode to machine code at run time. During this conversion, JIT performs some optimization on code so that code can be executed very fast, and it also improves the performance of execution. At the run time if the program contains one instruction, which can be executed more than one time. At that time the JVM ( Java virtual machine ) was used to read the instruction and convert that instruction to machine code and execute that instruction on the CPU. Here the term " compiler" refers to a translator from the instruction set of a Java virtual machine (JVM) to the instruction set of a specific CPU.
Working on JIT ( Just in time ) compiler?
To understand how JIT works? First, let's understand how to compile and run a simple java program.
Abc.java
class Abc{
public static void main(String args[]){
System.out.println(" Hi ! I am abc ");
}
}
Output :

Syntax to compile Java program :
javac filename.java
Syntax to run Java program :
java filename

The figure shown above describes the complete execution of the Java program. The execution of the Java program is completely different when compared to c++. Because the Java program is compiled as well as interpreted. The compiler and the interpreter take part in the entire execution process.
Starting with the small rectangle box. In the first step i.e., the first box we have our Java code which is nothing but where we type our Java code and save our Java file as filename.java here I took the example as abc.java this is the very first step. And the next step is to invoke the java compiler by using the "javac" command.
When we type javac in our cmd (command prompt) the compiler is executed or invoked. Now the compiler will compile the entire java file and convert it into byte code with an extension “.class” i.e., filename.class here in the diagram it is compiled to abc.class. So, when we compile, we will be getting a class file that is written in jewerish language which we cannot understand or read. In the second step the compiler ofcourse, checks for syntax errors and different errors we had in our code.
If there is no error, then it will generate the bytecode or else it goes back to the first step. This stage is known as the bytecode stage. These first three stages ( java program, compiler, bytecode) are the stages compile time or the compilation stages.
When we invoke the Java program to run the bytecode i.e. when we give "java filename" in our cmd. This step is considered the fourth step. Now this byte code i.e., abc.class is loaded by the “Class loader”. “Class loader” is again a program inside JVM ( Java virtual machine ). It loads bytecode in JVM. Then there is one more program “Bytecode verifier” inside JVM. The " Bytecode verifier" checks for any errors or bugs in the bytecode. So this all happens inside JVM. After this “ Interpreter “ is invoked.
The basic difference between an Interpreter and a compiler is?
The compiler compiles the complete or entire file. For example, if the file contains ten lines. Then the compiler takes all lines and converts them into bytecode or class files only if there are no errors in the program. Whereas the interpreter interprets each line one by one. Now consider the same example, for ten lines of a file the interpreter first takes the first line and converts it into the class file or byte code. And then does the same with the second file.
So, after the " Bytecode verifier " verifies the class file it sends the file to either "Interpreter" or "JIT" depending on some conditions. The interpreter interprets the code line by line and sends it out of JVM i.e., to OS (Operating System) or any hardware, and executed.
Step 1: Java code (filename.java)
Step 2: Entire java file is converted into the class file with an extension ".class" by invoking javac in cmd.
Step 3: Checks for any error and converts it into bytecode.
Step 4: Bytecode is loaded by “Class loader”.
Step 5: Bytecode verifier checks for any errors or bugs in the class file.
Step 6: Depending upon JIT type. The JIT compiler or Interpreter is invoked.
Step 7: Sent to OS to get output.
To understand the JIT compiler, we should go with two cases.
Case 1:
Let us assume we do not use the JIT compiler in this case.

Here we have five lines of code, this code is already a class code. Currently, we are at stage 6. Now this byte code is sent to the interpreter. The interpreter interprets the class code line by line and generates the corresponding outputs and transfers them to the CPU to execute.
As this is just a five-line code we will get our required output within a fraction of a second. If our program consists of thousands of lines. Then the interpreter goes line by line so it will take some time to produce output. The major point to note in case 1 is last two lines are the same. Even though they are the same the interpreter considers them as different lines and gives the same output. It is unnecessary, we could have saved one instruction.
Case 2:

In case 2 we have the JIT compiler involved. The bytecode first goes to the JIT compiler. The JIT compiler analyses the entire code (since it is a compiler it analyses the entire code) and it sees if any redundant lines can be excluded. Her last line is extra if it is removed also the output will not change. So, it excludes the last line and transfers the first four lines to the interpreter. Now the interpreter assumes the bytecode has only four lines and interprets only four lines. And the output will also be the first four lines only.
We observe that one line was saved. This is where the JIT compiler comes into the picture. Invoking the JIT compiler is dependent on what type of JIT compiler is used. Some JIT compilers are very aggressive they are invoked every time, and some are not. Depending upon the coding and inbuilt nature of the JIT compiler it is being invoked. But depending upon the huge size the JIT compiler can be very efficient, and it can optimize the code and make the processing and execution very fast.