Java Virtual Machine (JVM) Architecture

What is the JVM?

The JVM (Java Virtual Machine) is an abstract computing machine that enables a computer to run a Java program. It acts as a runtime engine that calls the main method inherent in Java code. The JVM is the core reason behind Java's famous slogan: "Write Once, Run Anywhere" (WORA), as it compiles source code into platform-independent bytecode.

JVM Architecture Reference Diagram

Use this flowchart to see how subsystems connect and pass runtime data:

JVM Architecture Flowchart

1. Class Loader Subsystem

Responsible for loading, linking, and initializing the class files (.class) into the JVM memory. It operates in three main phases:

A. Loading

Reads the binary data of the class and stores it in the method area. There are three built-in class loaders:

  • Bootstrap Class Loader: Loads core Java API classes (from rt.jar).
  • Extension Class Loader: Loads classes from the extension directories (jre/lib/ext).
  • Application/System Class Loader: Loads classes from the application classpath.

B. Linking

  • Verification: Ensures the correctness of the .class file structure against JVM rules.
  • Preparation: Allocates memory for class variables (static fields) and initializes them to default values.
  • Resolution: Replaces symbolic references in the code with direct references.

C. Initialization

The final phase where all static variables are assigned their actual defined values, and static blocks are executed.

2. Runtime Data Areas (Memory)

This is the memory allocated by the JVM to run programs. It is divided into five distinct components:

Shared Across All Threads:

  • Method Area: Stores class-level data such as runtime constant pools, field/method data, and code for methods and constructors.
  • Heap Area: The runtime data area from which memory for all class instances and arrays is allocated. This is the primary target for Garbage Collection.

Per-Thread (Private to Each Thread):

  • JVM Stack: Stores local variables and partial results. Each thread has its own stack, and a new "Frame" is pushed onto the stack every time a method is called.
  • PC (Program Counter) Registers: Contains the address of the JVM instruction currently being executed by the thread.
  • Native Method Stack: Holds native method information (written in languages like C/C++) used in the application.

3. Execution Engine

Once the bytecode is loaded into memory, the Execution Engine executes the instructions line by line. It contains three main components:

A. Interpreter

Reads the bytecode instructions and executes them sequentially. While quick to start up, it can be slow when executing repeated blocks of code (like loops), as it re-interprets the code every time.

B. JIT (Just-In-Time) Compiler

Counterbalances the interpreter's speed issue. It monitors code execution and compiles frequently repeated bytecode ("hot spots") into native machine code, boosting execution speeds significantly.

C. Garbage Collector (GC)

An automated program that runs in the background. It tracks live objects and automatically destroys unreferenced, unreachable objects to reclaim heap memory.

4. Native Interfaces & Libraries

The bridge between Java code and external operating system resources.

Java Native Interface (JNI)

An API wrapper framework that allows Java code running inside the JVM to interact and call applications/libraries written in native hardware-level languages like C, C++, or Assembly.

Native Method Libraries

A collection of the actual native libraries (e.g., .dll files on Windows or .so files on Linux) required by the execution engine during code operation.

Quick Reference: Memory Lifetime & Sharing

A breakdown of how memory regions manage data scope and accessibility:

Memory Area Scope / Access Primary Purpose
Method Area Shared by all threads Class structures, metadata, static variables
Heap Area Shared by all threads Instantiated objects and arrays
JVM Stack Per thread private Local variables, method execution frames
PC Register Per thread private Tracks next instruction to execute
Native Stack Per thread private C/C++ native method execution data