Java Virtual Machine (JVM) Structure and Components
The Java Virtual Machine (JVM) is an abstract computing machine that enables Java applications to run on any platform. It provides runtime services such as memory management, security, and execution of Java bytecode. The JVM consists of the following major components:
1. Class Loader Subsystem
The Class Loader is responsible for loading .class
files into memory and linking them for execution. It follows the Lazy Loading principle, meaning classes are loaded only when required.
Key Processes:
- Loading: Reads
.class
files and loads bytecode into memory. - Linking: Verifies bytecode, prepares static fields, and resolves references.
- Initialization: Executes static initializers and assigns values to static fields.
Types of Class Loaders:
- Bootstrap ClassLoader – Loads Java’s core classes (
java.lang
,java.util
, etc.). - Extension ClassLoader – Loads classes from the
ext
directory (java.ext.dirs
). - Application ClassLoader – Loads classes from the application’s
classpath
. - Custom ClassLoader – Developers can define their own class loaders.
2. Runtime Data Areas
The JVM organizes memory into various runtime areas to efficiently manage execution.
a) Method Area (Shared)
- Stores class-level data such as:
- Class structures (method metadata, field information).
- Static variables.
- Constant pool (string literals, class/method references).
b) Heap (Shared)
- Stores objects and instance variables.
- Managed by the Garbage Collector (GC) to free unused objects.
c) Java Stack (Per Thread)
- Stores method execution frames for each active thread.
- Each frame contains:
- Local Variables: Stores method parameters and local variables.
- Operand Stack: Stores intermediate calculations.
- Frame Data: Stores method return addresses and execution context.
d) PC Register (Per Thread)
- Stores the current instruction address of the executing thread.
e) Native Method Stack (Per Thread)
- Stores native method calls (methods written in languages like C/C++ using JNI).
3. Execution Engine
The Execution Engine is responsible for executing Java bytecode.
Components of Execution Engine:
a) Interpreter
- Translates bytecode line-by-line into machine instructions.
- Slower due to repeated interpretation.
b) JIT Compiler (Just-In-Time Compiler)
- Converts frequently used bytecode into native machine code at runtime.
- Uses hotspot detection to optimize performance.
- Supports techniques like method inlining and loop unrolling.
c) Garbage Collector (GC)
- Automatically reclaims memory occupied by unused objects.
- Uses different GC algorithms (e.g., Mark-Sweep, G1 GC).
4. Native Interface (JNI)
- Allows Java programs to interact with native code (C/C++).
- Used when Java needs system-level access.