Unlocking the JVM: A Deep Dive into Java’s Runtime Architecture
This article explains the Java Virtual Machine’s architecture, covering its role as the JRE implementation, the three main subsystems—class loader, runtime data area, and execution engine—and detailing components such as class loading phases, memory areas, the interpreter, JIT compiler, and garbage collection.
Understanding the JVM Architecture
Every Java developer knows that bytecode is executed by the JRE, which is an implementation of the Java Virtual Machine (JVM). The JVM analyzes bytecode, interprets it, and executes it. Knowing the JVM’s architecture helps developers write more efficient code.
What is the JVM?
The JVM is a software implementation of a virtual machine that runs Java programs. Java follows the “write once, run anywhere” principle, compiling source files into .class files, which the JVM loads and executes.
How the JVM Works
The JVM consists of three major subsystems:
Class Loader Subsystem
Runtime Data Area
Execution Engine
1. Class Loader Subsystem
The class loader handles dynamic loading of classes at runtime, linking them and initializing them when first referenced.
1.1 Loading
Classes are loaded by three loaders: the bootstrap class loader (loads from the bootstrap class path, primarily rt.jar), the extension class loader (loads from the JRE’s lib/ext directory), and the application class loader (loads from the application class path).
1.2 Linking
Verification – checks the correctness of bytecode.
Preparation – allocates memory for static variables with default values.
Resolution – replaces symbolic references with actual memory references.
1.3 Initialization
During initialization, static variables receive their assigned values and static blocks are executed.
2. Runtime Data Area
The runtime data area is divided into five components:
Method Area – stores class-level data, including static variables; shared by all JVM instances.
Heap – stores all objects and arrays; there is a single heap per JVM.
Stack – each thread has its own stack containing frames for method calls, local variables, operand stack, and frame data. The stack is thread‑local and therefore thread‑safe.
PC Register – each thread has a program counter register that points to the next instruction to execute.
Native Method Stack – stores information for native methods, with a separate stack per thread.
3. Execution Engine
The execution engine runs the bytecode loaded into the runtime data area.
Interpreter
The interpreter reads and executes bytecode instruction by instruction, which is simple but slower for repeated method calls.
JIT Compiler
The Just‑In‑Time compiler eliminates the interpreter’s drawback by compiling frequently executed bytecode into native machine code, improving performance.
Intermediate Code Generator – generates intermediate code.
Code Optimizer – optimizes the intermediate code.
Target Code Generator – produces machine code.
Analyzer – detects hot spots (methods called repeatedly).
Garbage Collector
The garbage collector reclaims memory of objects that are no longer referenced. It can be hinted with System.gc(), though execution is not guaranteed.
Java Native Interface (JNI)
JNI allows the JVM to interact with native libraries, providing the native methods required by the execution engine.
Native Method Library – a collection of native libraries needed by the execution engine.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
