JVM (Java Virtual Machine) Architecture - Java Tutorial

JVM (Java Virtual Machine) Architecture

BLUF: Mastering JVM (Java Virtual Machine) Architecture is a key requirement for any Java developer. This lesson breaks down the object-oriented principles and syntax required to use this concept in real-world applications.
Write Once, Run Anywhere Tip: JVM (Java Virtual Machine) Architecture

Java's versatility is unmatched. Learn how JVM (Java Virtual Machine) Architecture fits into the Java ecosystem and improves your code structure in the tutorial below.

The JVM, short for Java Virtual Machine, functions as a conceptual machine, outlining a standard that delivers an operational environment where Java bytecode can run. This section will delve into a comprehensive examination of the JVM and its structure.

What is JVM (Java Virtual Machine)?

JVM stands for Java Virtual Machine and it is:

  • A specification specifying the workings of the Java Virtual Machine. However, the implementation provider is independent of choosing the algorithm. Oracle and other companies have provided its implementation.
  • An implementation Its implementation is known as JRE (Java Runtime Environment).
  • Runtime Instance Whenever we write a java command on the command prompt to run the Java class, an instance of JVM is created.
  • Platform Dependency of JVM

Java Virtual Machines (JVMs) are accessible across a variety of hardware and software environments, indicating that JVMs are platform-specific, tailored to various operating systems and hardware structures.

JVM implementations are customized for particular platforms in order to enhance performance and guarantee compatibility. This approach ensures that Java applications can operate reliably across a wide range of environments.

Functions of JVM

The JVM performs following operations:

  • Verifies code: It checks the bytecode for security and correctness to ensure it does not violate Java’s safety rules.
  • Executes code: The JVM converts bytecode into machine-level instructions and executes them using the interpreter or JIT compiler.
  • Provides a runtime environment: It manages memory, threads, and system resources required to run Java applications efficiently.
  • JVM Internal Definitions

JVM Provides Definitions for the:

  • Memory areas: The JVM defines memory regions such as heap, stack, method area, and PC register for program execution.
  • Class file format : It specifies a standard structure for .class files so they can be understood by any JVM.
  • Register set : The JVM uses registers like the program counter to track instruction execution.
  • Garbage-collected heap : It automatically manages memory by removing unused objects through garbage collection.
  • Fatal error reporting and more : The JVM handles serious runtime errors and provides diagnostic information for debugging.
  • JVM Architecture

The architecture of the Java Virtual Machine (JVM) dictates the processes involved in loading, running, and overseeing Java programs in memory to guarantee both platform agnosticism and optimal operational speed. Key elements of the JVM architecture include:

1) Classloader

Classloader is a subsystem of JVM which is used to load class files. Whenever we run the Java program, it is loaded first by the classloader. There are three built-in classloaders in Java.

  • Bootstrap ClassLoader: It is the first classloader, which is the superclass of the Extension classloader. It loads the rt.jar file that contains all class files of Java Standard Edition, such as the java.lang package classes, java.net package classes, java.util package classes, java.io package classes, java.sql package classes, etc.
  • Extension ClassLoader: It is the child classloader of Bootstrap and the parent classloader of the System classloader. It loads the jar files located inside the $JAVA_HOME/jre/lib/ext directory.
  • System/Application ClassLoader: It is the child classloader of the Extension It loads the classfiles from the classpath. By default, the classpath is set to the current directory. You can change the classpath using the "-cp" or "-classpath" switch. It is also known as the Application classloader.
  • Runtime Data Areas: JVM allocates memory for various runtime data areas during program execution. These include the method area, heap, stack, PC (Program Counter) register, and native method stacks. The method area stores class structures, method code, static variables, and constant pool. The heap is where objects are allocated, while the stack holds method invocation frames. The PC register keeps track of the currently executing JVM instruction, and native method stacks are used for executing native methods.
  • Execution Engine: The execution engine is responsible for executing the compiled Java bytecode. It consists of two components: the interpreter and the just-in-time (JIT) compiler. The interpreter reads and executes bytecode instructions one by one, while the JIT compiler compiles frequently executed bytecode sequences into native machine code for improved performance.
  • Garbage Collector: JVM includes a garbage collector responsible for reclaiming memory occupied by objects that are no longer in use. The garbage collector identifies and removes unreachable objects, freeing up memory for new allocations. Various garbage collection algorithms are available, each with its own trade-offs in terms of performance and memory overhead.
  • Native Method Interface (JNI): JNI enables Java code to interact with native libraries and perform operations not directly supported by the Java language. It allows Java applications to call functions written in languages like C and C++, providing flexibility and access to platform-specific capabilities.

File Name: ClassLoaderExample.java

Example

//Let's see an example to print the classloader name

public class ClassLoaderExample

{

    public static void main(String[] args)

    {

        // Let's print the classloader name of current class. 

        //Application/System classloader will load this class

        Class c=ClassLoaderExample.class;

        System.out.println(c.getClassLoader());

        //If we print the classloader name of String, it will print null because it is an

        //in-built class which is found in rt.jar, so it is loaded by Bootstrap classloader

        System.out.println(String.class.getClassLoader());

    }

}

Output:

Output

sun.misc.Launcher$AppClassLoader@4e0e2f2a

null

Explanation

The following Java snippet illustrates the process of displaying the classloader name for a specified class. Within the primary function of the ClassLoaderExample class, we utilize the syntax ClassLoaderExample.class to access a pointer to the Class object that represents the ClassLoaderExample class. Subsequently, we invoke the getClassLoader function on this Class object to fetch the classloader responsible for loading the ClassLoaderExample class.

The classloader commonly referred to as the System/Application classloader is responsible for loading user-defined classes. To demonstrate this, we can retrieve the classloader name for the String class by utilizing String.class.getClassLoader. In this particular case, the return value is null. This occurs due to String being a built-in class within the Java Standard Edition, residing in rt.jar. The Bootstrap classloader, responsible for loading rt.jar and implemented in native code, does not have an associated Java classloader object. Hence, the null outcome when attempting to access the classloader for the String class.

Java offers internal classloaders for developers to use. When creating a custom classloader, it is necessary to inherit from the ClassLoader class.

2) Class (Method) Area

Class(Method) Area stores per-class structures such as the runtime constant pool, field, and method data, and the code for methods.

  • Runtime Constant Pool: The runtime constant pool is part of the Class(Method) Area and consists of constant pool entries. These are used to store symbolic references, literals, and other constant values required by the class. These include class and interface names, method and field names, string literals, and numeric literals.
  • Field Data: The Class(Method) Area also stores information about the fields declared within a class, including their names, types, and access modifiers. This data is used by the JVM to access and manipulate object fields at runtime.
  • Method Data: Along with field data, the Class(Method) Area contains information about the methods declared within a class, including their names, return types, parameter types, and bytecode instructions. This information is used by the JVM to invoke methods and execute bytecode instructions during program execution.
  • 3) Heap

The Heap is the runtime data area in which objects are allocated.

  • Object Allocation: The Heap is responsible for allocating memory for objects dynamically created during program execution. When an object is instantiated using the new keyword or by invoking a constructor, memory is allocated on the Heap to store the object's data.
  • Garbage Collection: The Heap is managed by the JVM's garbage collector, which periodically scans the Heap for objects that are no longer in use or reachable by the application. Garbage collection involves reclaiming memory occupied by these unused objects, freeing up space for new allocations.
  • Heap Structure: The Heap is typically divided into two main areas: The Young Generation and the Old Generation (also known as the Tenured Generation). The Young Generation is further divided into the Eden Space and Survivor Spaces, while the Old Generation contains long-lived objects that have survived multiple garbage collection cycles.
  • 4) Stack

In Java, the Stack stores frames containing local variables and intermediate results. It is involved in handling method calls and returns within the program's execution flow.

Every thread is associated with its own JVM stack, which is generated concurrently with the thread itself.

When a method is called, a new frame is generated, and it is eliminated once the method call finishes.

  • Frame Composition: Each frame includes local variables, operand stacks, and a connection to the runtime constant pool of the ongoing method. Local variables hold method arguments and local variables, while the operand stack is utilized for temporary outcomes and operand manipulation while the method is running.
  • Method Call: The stack is essential for method calls and returns. As a method is called, a fresh frame is formed and added to the stack. After the method's execution is done, the frame is removed from the stack, and the control goes back to the calling method.
  • 5) Program Counter Register

The PC register, short for Program Counter register, holds the memory location of the instruction in the Java virtual machine that is presently running.

The Program Counter (PC) register is a distinctive register found in the Java Virtual Machine (JVM) that holds the memory location of the instruction currently being executed.

  • Instruction Pointer Role: The PC register functions as an instruction pointer, directing the JVM as it processes the series of bytecode instructions in progress.
  • Thread-specific Functionality: Similar to the Java Stack, every thread in a Java program possesses its individual PC register, enabling multiple threads to run instructions simultaneously without causing conflicts.
  • 6) Native Method Stack

It encompasses all the built-in methods utilized within the application.

The Native Method Stack is a designated memory region in the Java Virtual Machine (JVM) that is reserved for running native methods. These native methods are typically implemented in programming languages like C or C++. Here are some key points to note about the Native Method Stack:

Invocation of Native Methods: In Java programming, when a native method is called by a Java application, the control flow moves to the Native Method Stack, where the code of the native method is executed.

7) Execution Engine

It contains:

  • A virtual processor
  • Interpreter: Read bytecode stream then execute the instructions.
  • Just-In-Time(JIT) Compiler: It is used to improve the performance. JIT compiles parts of the byte code that have similar functionality at the same time, and hence reduces the amount of time needed for compilation. 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.
  • 8) Java Native Interface

The Java Native Interface (JNI) is a framework that facilitates communication with applications developed in different languages such as C, C++, Assembly, and others. Java leverages the JNI framework to output information to the Console or interact with operating system libraries.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience