For Developers

Java Virtual Machine (JVM): Introduction and Its Architecture

Java Virtual Machine (JVM): Introduction & Its Architecture

JVM stands for Java Virtual Machine. It is essentially a virtual machine or runtime environment that allows Java programs to run and operate on multiple devices and operating systems.

Java programs cannot run on machines that don’t have JVM support. It is an integral part of the Java Runtime Environment (JRE). JVM features many specifications that work together to run Java programs. It is platform-dependent by nature, i.e., every operating system has a different JVM.

Here is how the JVM works

Java applications are referred to as WORA (Write Once, Run Anywhere). Java programmers can write Java code on one platform and expect it to work on all Java-enabled systems. JVM makes this possible. Developers don’t have to worry about configuring and installing JVM as it is included in the JDK package.

The source code in Java is compiled to bytecodes. Multiple processes are used within a JVM to convert this Java bytecode into machine code.

The compiler creates .class files when we compile .java files. These contain bytecode and have the same class names as the .java files. When we run .class files, JVM executes the following operations:

  • Loads bytecode
  • Verifies bytecode
  • Executes bytecode
  • Provides a runtime environment to support various applications

JVM also helps in managing and optimizing resources during program execution by defining:

  • Memory area
  • Register set
  • Garbage collection
  • Class file format, and
  • Reporting fatal errors

JVM architecture

There are three notions of JVM in Java: Implementation, Specification, and Instance.

Let’s look at each of them.

Implementation: Also known as JRE (Java Runtime Environment).

Specification: A document that describes the requirements for JVM implementation.

Instance: A JVM instance is created whenever you run a java class file.

JVM architecture can be divided into three major subsystems:

  1. ClassLoader
  2. Memory area / Runtime memory
  3. Execution engine

1. ClassLoader

JVM loads the compiled .class files to run Java applications, and to perform this action; a JVM relies on its ClassLoader.

ClassLoader reads the .class file generated by the javac command and extracts core information. Then it stores this information in the Method Area.

The ClassLoader allows you to retrieve information such as classes, their names, variables, and methods.

Classloaders employ lazy-loading and cache to make class loading efficient and effective.

For example-

// Printing the classloader  

public class ClassLoaderTuring  
{  
    public static void main(String[] args)  
    {  
         
        Class t=ClassLoaderTuring.class;  
        System.out.println(t.getClassLoader());  
        
        System.out.println(String.class.getClassLoader());  
    }  
}    

OUTPUT-

java -cp /tmp/hGDqtWN46U ClassLoaderTuring
jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f
null

JVM architecture uses three classloaders:

  • Bootstrap/Primordial ClassLoader
  • Extension ClassLoader
  • System/Application ClassLoader

i. Bootstrap ClassLoader

Bootstrap ClassLoader is the machine code that kickstarts the operation when Java Virtual Machine begins to run.

Bootstrap ClassLoader is not a Java class; its task is to load the first Java ClassLoader. It loads the rt.jar file containing the necessary code to support the Java Runtime Environment (JRE), including class files such as java.util, java.lang, java.io package classes.

Bootstrap ClassLoader is also known as the Primordial ClassLoader.

ii. Extension ClassLoader

The Extension ClassLoader (the child of Bootstrap ClassLoader) loads core java class extensions from the JDK Extension Library.

It loads files from the jre/lib/ext folder or other directories pointed by the system property java.ext.dirs.

iii. System ClassLoader

It is responsible for loading all application-level class files associated with the application mentioned in the classpath (-cp).

Application ClassLoader is also known as the System ClassLoader. It is the child of Extension ClassLoader.

The three most essential functions of a ClassLoader are Loading, Linking, and Initialization.

a. Loading

The ClassLoader loads files from secondary memory to main memory (RAM) for execution.

ClassLoader takes the .class file and generates the binary data. It then saves it in the method area.

JVM keeps some information in the method area for each .class, including:

  • The fully qualified name of its immediate parent class and the loaded class.
  • The details of interfaces or classes related to the .class file.
  • The details of variables, modifiers, method information, etc.

JVM loads the .class file and creates an object of type Class to represent it in the heap memory.

Developers can use the Class object to obtain class-level information like the class name, parent name, methods, and variable data.

b. Linking

The linking process follows these three main steps:

Verification: This step ensures that the .class file is correct. Then it checks whether a valid compiler did the file’s creation and generation. And, if the verification fails, we get a java.lang.VerifyError exception and the linking process comes to a halt.

Preparation: JVM allocates memory to static Class variables and initializes it to default values.

Resolution: It is the process of replacing symbolic references with new ones and involves searching in the method area to locate a referenced entity.

c. Initialization

The final step in the class-loading process is where the static variables are assigned their defined values, and static blocks are executed.

2. JVM memory area

JVM memory area is the second element of Java Virtual Machine. The Runtime Data Area has five sub-areas.

i. Method area

There is only one method area per JVM, and this runtime area is common to all threads. It stores the structure of each class, such as class name, method data, methods, variables information, etc.

ii. Heap:

The Heap memory area stores the object and its instance variable. Every time you create an object in Java, it gets moved into the heap. The Heap area denotes a shared memory area.

iii. Stack:

Stack (also known as thread stack) is a data area within the JVM memory created for one execution thread.

JVM stacks stores partial results, local variables, and data for method invocations and returns.

iv. PC register:

The PC register stores the address of the Java Virtual Machine instruction address currently being executed. Each thread is assigned a separate PC register.

v. Native method stack:

It contains all native methods needed for an application. Native methods use languages other than Java.

3. Execution engine

It is the core area of Java Virtual Machine. The execution engine can communicate with different memory areas in JVM.

Every thread in a Java application is an instance of the execution engine of the virtual machine.

The execution engine executes the byte code assigned to runtime data areas via the ClassLoader. It consists of three main components:

  • Interpreter
  • JIT Compiler
  • Garbage Collector

i. Interpreter:

The interpreter reads, interprets, and executes the bytecode line-by-line.

However, if you call one method more than once, interpretation is required each time. And this is the downside to the interpreted language.

ii. Just-In-Time Compiler (JIT):

It’s used in JVM to improve the efficiency of the interpreter. Also, it compiles all the bytecode and converts it to native code.

When the interpreter receives repeated method calls, JIT provides native code directly for that section. It reduces the need to re-interpret, thereby improving efficiency.

iii. Garbage collector:

It is a crucial feature of JVM architecture. Every object created during program execution consumes some memory. These objects are no longer referenced by the program later and are therefore no longer needed.

The garbage collector removes these unreferenced objects from the memory to manage and improve memory efficiency.

Native Method Interface

Native methods allow you to use code from other languages, such as C and C++, in your Java code. You can use them when Java doesn’t offer the functionality you require.

Native Method Libraries

It’s a collection of native libraries (C, C++) required by the execution engine.

FAQs

i. Why is JVM used in Java?

Ans. JVM is responsible for converting the bytecode into machine code before running Java applications on any platform.

ii. Why is JVM called an abstract machine?

Ans. JVM can be described as an abstract machine because it doesn't exist physically. It's a specification that provides the runtime environment where Java bytecode can be executed.

iii. Is the JVM platform independent?

Ans. It is platform dependent by nature. There is a JVM for every type of operating system i.e. Windows, macOS, Linux.

iv. What is the default size of JVM?

Ans. By default, the JVM heap size is 256MB.

v. What is the difference between JRE and JVM?

Ans. JRE provides an environment that allows you to run the Java software locally. Where JVM is responsible for converting the bytecode into machine code and making the Java program write-once-run-anywhere.

Conclusion:

The JVM was explicitly designed to run on any platform. Initial plans were to run the JVM on set-top boxes. But Sun Microsystems soon realized the market wasn't ready and they decided that the platform could be extended to work on desktop computers. Sun created the binary executable format that they called Java bytecode to support all of these applications. Developers can now run their Java programs on the JVM, the virtual machine, and take advantage of its performance, features, and extensive class library.

Press

Press

What's up with Turing? Get the latest news about us here.
Blog

Blog

Know more about remote work.
Checkout our blog here.
Contact

Contact

Have any questions?
We'd love to hear from you.

Hire and manage remote developers

Tell us the skills you need and we'll find the best developer for you in days, not weeks.

Hire Developers