Introduction to Java Virtual Machine
In this article, we will learn about Java Virtual Machine, aka “JVM”. Java Virtual Machine is a Virtual Machine that allows a computer system to run/execute Java Programs. Basically, JVM is an engine, which works as a runtime environment for Java code. JVM converts the java code into machine language. When you run a compiled .class file, it goes to JVM, and then JVM returns the output. Java Virtual Machine is a part of JRE, which stands for “Java Runtime Environment”. Basic tasks for a Java Virtual Machine consist of Loading the code, then verifying the code and executing the code. Also, provide the runtime environment for code execution. JVM consists of various components like Classloader, List of space assigned by JVM like Stack, an Execution Engine and a few native libraries.
The architecture of Java Virtual Machine
Following is the Architecture of Java Virtual Machine:
As shown in the image above, Java Virtual Machine Architecture consists of various components. Let’s learn about every specific component individually.
As the name suggests, it is a component responsible for Loading Class files. Loading, Linking and initializing a class file are the major functions of the Loader. The loader does it work in runtime.
- Loading: Basically, the loader reads the .class file and then generates the binary code and saves it in a method area. Bootstrap Classloader, Extension Classloader, and Application Classloader are the various ClassLoaders responsible for loading various classes.
- Linking: Three major functions like Verification, Preparation, and Resolve. It starts with .class file verification. If verification fails, it gives a run time verification exception. Later, Memory is allocated to the variables with default values. Then, finally, the symbolic memory references are replaced with direct reference from the memory area.
- Initializing: This is the final part of ClassLoader. Original values are assigned to all the static variables, followed by the execution of Static Block. This part executes from the top to the bottom of a class.
Details of an object and instance variables are all stored here. It is a shared memory area, which means the data stored here is not thread-safe.
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
One of the most relatable errors is the “OutOfMemoryError” exception, which means the JVM cannot allocate an object in the Heap area, or memory allocation cannot be done for the same object.
This is where a separate runtime stack is created for every new thread. Also known as a Run-Time Stack, every time a method is called upon, all the details are stored in the corresponding runtime stand, and after the completion of the method, these details are removed from the stack.
For every single thread, a separate PC (Program Counter) register is created, which stores the address of the current execution instruction, which, later, will be updated with the next instruction. This memory area is quite small and is of fixed size.
Native Method Stack
It is one of its own kind of memory area, which is invoked by a thread and then the thread is in a whole new level where structure and security restrictions implied by Java Virtual Machine are no longer in exercise. Compared to other runtime memory areas, the memory occupied by the native method stacks has no fixed size, with no limitations in increment or decrement.
Java Native Interface
JNI simply interacts with the below mentioned Native Method Libraries, which are of C, C++ implementation, and provide the same to the execution engine. Direct Access to assembly code is allowed by JNI. For a JVM, Java and Native are the two types of codes. The JNI smoothly establishes a well-defined link between these two.
Native Method Libraries
Collection of Native Libraries, as required by the Execution Engine.
Well, now we have a java program into bytecode, which is being assigned to the above-explained data areas via a class loader, and now the bytecode will be executed by the execution engine. Execution Engine simply reads the bytecode in units, like a machine reading code lines one by one. The bytecode is a human-readable format, which is why the machine cannot read it as it is and needs to be converted to a machine-readable format, where the below components are utilized for the interpretation purpose.
The Execution Engine has three major components, which are Interpreter, JIT Compiler and a Garbage Collector.
Simply executes the bytecode in a sequential method. A command-line query makes a call with a compiled file as an argument. The interpreter is quite quick in interpreting and executing commands one by one, which happens faster than the JIT compiler to compile the code.
java class name
A main() class is must in a compiled .class file.
2. JIT Compiler
One of the most important components of the Java Runtime Environment which enhances the Java Application performance at run time. No other component has more impact on performance than the JIT Compiler. This is a default compiler and is activated when any Java method is called.
3. Garbage Collector
As the name suggests, it does have something to do with garbage; Garbage Collector simply searches for every possible object available in the JVM heap space, checks if it is in use, and then delete the unused ones. So, it simply marks the pieces of memory which are in use or not. Then it goes on sweeping, where it simply removes the object marked. The best use case is that no manual memory allocation system is needed as the Garbage Collector does the job of automatically removing unused memory space. As this is an automatic task, no programmer has control over scheduling any time slot for specifically cleaning tasks and requires more CPU power as it searches for object references.
Though it is not mandatory to have a clear understanding of how JVM works for the purpose of writing Java code, it is immensely helpful. For a developer who understands the working of JVM, he will write better and optimized code, however long or complex the requirement is. Besides the description provided here, JVM provides a wide range of features and technologies. These features can be used to improve the performance as needed by a specific vendor.
This is a guide to Java Virtual Machine. Here we discuss the architecture of the java virtual machine along with its various components. You may also look at the following articles to learn more –