In this tutorial, we will learn about two core components of the Java environment (Java Virtual Machine and the Just In Time compiler). We will learn about their internal structure and how they work to execute a Java program.
JVM is virtually a machine on which the Java programs actually run on. A Java program cannot run on a machine without JVM. It is a core part of the Java Runtime Environment (JRE). The JVM is loaded with many specifications that altogether work to successfully run a Java program. It is platform-dependent by nature i.e for each type of operating system there is a different JVM.
A developer need not worry about installing and configuring JVM. It comes built-in with the JDK package.
The platform-independent feature of Java is made possible by JVM. The JVM is the one that can convert the Java bytecode into a machine-understandable code. The conversion of Java Bytecode to machine code takes place in multiple specifications inside a JVM.
The ClassLoader is a subpart of JVM. It mainly reads the .class file that is generated using the javac command, extracts some core information from that file, and stores that information in the Method Area. The ClassLoader can get information like classes and their names, variables, methods, interfaces, etc.
A method area is like a store where all the class level information like class names, variable names, method names, enums, etc. are stored. It is a unique area in JVM which is shared among other classes.
We know Java is an object-oriented programming language where everything is in the form of objects. These objects are real entities that need memory to work. The Heap in JVM stores all the data & information about objects that are created during the lifetime of execution of a Java program. Just like Method area, there is only one Heap Area which is a shared resource in JVM.
Program Counter Registers (PC Registers) address storing registers in JVM. These registers store the address of the current instruction that is being executed. Java is a multi-threaded programming language which means there can be multiple threads running at the same time. Java provides multiple PC Registers to store the address of each thread that is being executed.
The Execution Engine is the one that actually executes the Java bytecode (.class files) inside JVM. The execution engine reads the contents of the .class files line by line and extracts information that is then converted to machine code (which is understandable by the computer). The Execution Engine contains three subparts that collaboratively complete program execution.
A Native Method Stack is used to store information about the native methods that are used in a Java application. There is just one Native Method Stack for one execution thread. Multiple Native Method Stacks are used for multiple execution threads.
It is an interface between the JVM and other native libraries like C/C++. Whenever there is a need for external native libraries in JVM this interface is used. This interface can call native libraries or be called by native libraries.
Java programs are really fast in execution. This speed is achieved by the superior performance of Java Virtual Machine. The architecture of JVM has many sub-components that contribute to its performance. The main component on which its execution heavily relies is the Just In Time Compiler (JIT).
The JIT compiler interacts with the JVM at runtime and compiles similar bytecodes into native machine code. This machine code is easily understood by the host machine and can be executed really fast. Whenever there is a repetition of the same code that is being executed, the JIT compiler provides its native machine code at that instance so that the repeated code doesn’t take the same amount of process time again. This saves execution time and increases efficiency.
The JIT compiler achieves much higher execution efficiency only when there is the repetition of the same bytecode. JIT compiles similar bytecodes together and converts them to native machine code. JIT will not be much performance efficient when the repeated code is not frequent.
Oracle uses the Hotspot Compiler to increase the efficiency of program execution. Hotspot compiler identifies and prioritizes Java code so that code with higher priority gets compiled before low priority code.