Your path to becoming an Ethical Hacker! Hacking Academy Try It Now!

Exploring JVM and Its Architecture: What You Need to Know

Learn how JVM works and understand its architecture. Boost your Java skills with insights into Class Loader, Memory Structure, and Execution Engine.

In this post, you'll learn how the JVM works and understand its architecture.

Understanding JVM and its architecture can be challenging, but it's crucial for mastering Java. Dive in to demystify this complex topic and boost your Java skills!

Although JVM and its architecture can be challenging, this post will help you understand it better.

Exploring JVM and Its Architecture: What You Need to Know

What is JVM

The JVM (Java Virtual Machine) serves as the runtime engine for executing Java applications. It's responsible for calling the main method in Java code and is a component of the JRE (Java Runtime Environment).

Java applications are known as WORA (Write Once, Run Anywhere), meaning that code written on one system can run on any other system with a JVM without modifications. This cross-platform capability is made possible by the JVM.

When a .java file is compiled, the Java compiler generates .class files containing byte-code with the same class names as those in the .java file. These .class files undergo several processes when executed, which together outline how the JVM operates.

Exploring JVM and Its Architecture: What You Need to Know

Class Loader Subsystem

The Class Loader Subsystem is responsible for three main activities:

  • Loading
  • Linking
  • Initialization

Loading

The Class Loader reads the `.class` file, generates the corresponding binary data, and saves it in the method area. For each `.class` file, the JVM stores the following information in the method area:

  • The fully qualified name of the loaded class and its immediate parent class.
  • Whether the `.class` file is related to a Class, Interface, or Enum.
  • Modifiers, variables, and method information.

After loading the `.class` file, the JVM creates an object of type `Class` to represent this file in the heap memory. This `Class` object, predefined in the `java.lang` package, allows programmers to access class-level information such as the class name, parent name, methods, and variables. The `getClass()` method of the `Object` class can be used to obtain this object reference.

Example

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();

        // Getting hold of Class object created by JVM.
        Class c1 = s1.getClass();

        // Printing type of object using c1.
        System.out.println(c1.getName());

        // Getting all methods in an array
        Method[] m = c1.getDeclaredMethods();
        for (Method method : m)
            System.out.println(method.getName());

        // Getting all fields in an array
        Field[] f = c1.getDeclaredFields();
        for (Field field : f)
            System.out.println(field.getName());
    }
}

class Student {
    private String name;
    private int roll_No;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getRoll_no() { return roll_No; }
    public void setRoll_no(int roll_no) { this.roll_No = roll_no; }
}

Output:

Student
getName
setName
getRoll_no
setRoll_no
name
roll_No

Note: For every loaded `.class` file, only one `Class` object is created.

Student s2 = new Student();
// c2 will point to the same object where c1 is pointing
Class c2 = s2.getClass();
System.out.println(c1 == c2); // true

Linking

Linking involves three main steps: verification, preparation, and (optionally) resolution.

  1. Verification: Ensures the correctness of the `.class` file by checking whether it is properly formatted and generated by a valid compiler. If verification fails, a runtime exception `java.lang.VerifyError` is thrown. This process is handled by the ByteCodeVerifier component. Once verification is complete, the class file is ready for further processing.
  2. Preparation: Allocates memory for class static variables and initializes the memory to default values.
  3. Resolution: Replaces symbolic references in the bytecode with direct references by searching the method area to locate the referenced entities.

Initialization

In the initialization phase, all static variables are assigned their values as defined in the code and static blocks (if any) are executed. This process occurs from top to bottom within a class and follows the class hierarchy from parent to child.

Related Posts

Types of Class Loaders

The JVM utilizes several types of class loaders to load different types of classes:

Bootstrap Class Loader

Purpose: Every JVM implementation includes a bootstrap class loader that is responsible for loading core Java API classes from the “JAVA_HOME/jre/lib” directory, known as the bootstrap path.

Implementation: This loader is implemented in native languages like C and C++, ensuring high performance and integration with the underlying operating system.

Characteristics: Since the bootstrap class loader is part of the JVM, it is not represented by a Java object. It loads essential classes like `java.lang.Object`, `java.lang.String`, and other fundamental classes required for the JVM to function.

Extension Class Loader

Purpose: The extension class loader, a child of the bootstrap class loader, is tasked with loading classes from the extensions directories specified by the `java.ext.dirs` system property. By default, this includes the “JAVA_HOME/jre/lib/ext” directory.

Implementation: It is implemented in Java by the `sun.misc.Launcher$ExtClassLoader` class, allowing it to be more flexible and easily modified than the bootstrap class loader.

Use Case: This loader is used for loading classes that extend the standard Java platform, such as optional packages or libraries that add additional functionality to the JVM.

System/Application Class Loader

Purpose: The system (or application) class loader, a child of the extension class loader, is responsible for loading classes from the application classpath, which includes user-defined classes and libraries.

Implementation: It is implemented in Java by the `sun.misc.Launcher$AppClassLoader` class, leveraging Java's object-oriented features for enhanced functionality and management.

Characteristics: This loader uses the environment variable mapped to `java.class.path` to determine where to find the necessary classes. It is the default loader for applications running on the JVM.

Example Code to Demonstrate Class Loader Subsystem

public class Test {
    public static void main(String[] args) {
        // String class is loaded by bootstrap loader, hence null
        System.out.println(String.class.getClassLoader());

        // Test class is loaded by Application loader
        System.out.println(Test.class.getClassLoader());
    }
}

Output:

null
jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f

Note: The JVM follows the Delegation-Hierarchy principle to load classes. When the system class loader receives a request to load a class, it first delegates the request to the extension class loader. The extension class loader, in turn, delegates the request to the bootstrap class loader. If the class is found in the bootstrap path, it is loaded; otherwise, the request returns to the extension class loader, and then to the system class loader. If the system class loader fails to load the class, a runtime exception `java.lang.ClassNotFoundException` is thrown.

Exploring JVM and Its Architecture: What You Need to Know


JVM Memory Structure

The JVM memory is divided into several areas, each serving a specific purpose. Here’s a breakdown of the main memory areas:

Method Area

  • Purpose: Stores class-level information such as class name, immediate parent class name, methods, and variable information, including static variables.
  • Characteristics: There is only one method area per JVM, and it is shared among all threads, making it a shared resource.

Heap Area

  • Purpose: Stores information of all objects created in a Java application.
  • Characteristics: Like the method area, there is one heap area per JVM, and it is also a shared resource among all threads.

Stack Area

  • Purpose: For every thread, the JVM creates one runtime stack, which stores method calls.
  • Characteristics: Each block of this stack is called an activation record or stack frame, which holds all local variables for the corresponding method. The stack area is not a shared resource; each thread has its own stack. Once a thread terminates, its runtime stack is destroyed by the JVM.

PC (Program Counter) Registers

  • Purpose: Store the address of the current instruction being executed by a thread.
  • Characteristics: Each thread has its own PC register, ensuring that the execution context is maintained independently.

Native Method Stacks

  • Purpose: Store native method information for each thread.
  • Characteristics: Each thread has a separate native method stack, which is used to manage calls to native (platform-specific) methods.

This memory division allows the JVM to manage resources efficiently and provide a controlled environment for executing Java applications.

Exploring JVM and Its Architecture: What You Need to Know


Execution Engine

The execution engine is responsible for executing the ".class" files (bytecode) by reading the bytecode line by line, using data and information from various memory areas, and executing the instructions. The execution engine can be divided into several components:

Interpreter

  • Function: Interprets bytecode line by line and executes it.
  • Disadvantage: When a method is called multiple times, it requires repeated interpretation, which can be inefficient.

Just-In-Time (JIT) Compiler

  • Function: Enhances the efficiency of the interpreter. It compiles the entire bytecode into native code.
  • Advantage: When the interpreter encounters repeated method calls, the JIT provides direct native code, eliminating the need for re-interpretation and improving efficiency.

Garbage Collector

  • Function: Destroys unreferenced objects to free up memory.
  • More Info: For more on Garbage Collector, refer to dedicated resources on the topic.

Java Native Interface (JNI)

  • Function: Acts as an interface to interact with native method libraries (e.g., C, C++). It enables the JVM to call and be called by native libraries, which may be specific to the hardware.

Native Method Libraries

  • Function: A collection of native libraries (e.g., C, C++) required by the execution engine.
  • Purpose: Provides the necessary native libraries for executing specific tasks within the JVM.

The execution engine efficiently manages the execution of Java programs by using a combination of interpretation and compilation, along with garbage collection and interaction with native libraries.

FQAs

What is the JVM?

The JVM (Java Virtual Machine) is a runtime engine for executing Java applications. It calls the main method in Java code and is a part of the JRE (Java Runtime Environment).

What does the Class Loader Subsystem do?

The Class Loader Subsystem is responsible for loading, linking, and initializing classes and interfaces in the JVM.

How does the Just-In-Time (JIT) Compiler improve performance?

The JIT compiler improves performance by compiling the entire bytecode into native code, thus eliminating the need for repeated interpretation of frequently called methods.

What is the role of the Garbage Collector in JVM?

The Garbage Collector in the JVM is responsible for identifying and disposing of objects that are no longer referenced, freeing up memory for new objects.

What are the main memory areas in the JVM?

The main memory areas in the JVM are the Method Area, Heap Area, Stack Area, PC Registers, and Native Method Stacks. Each area serves a specific purpose in the execution of Java applications.

Post a Comment

Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.