JVM Architecture — Classloader, Memory Areas
The JVM is a virtual machine that runs Java bytecode. Understanding its architecture — classloaders, memory areas, and execution engine — helps you diagnose OutOfMemoryError, StackOverflowError, and performance bottlenecks.
JVM Memory Architecture
- Heap — where objects live. Shared by all threads. Divided into Young and Old generations.
- Young Generation (Eden + Survivor spaces S0/S1) — new objects allocated here. Cleared by Minor GC.
- Old Generation (Tenured) — long-lived objects promoted from Young. Cleared by Major/Full GC.
- Metaspace (Java 8+, replaced PermGen) — stores class metadata, method bytecode. Grows dynamically.
- Stack — per-thread. Stores stack frames (local variables, return addresses). Fixed or growing size.
- PC Register — per-thread. Points to the current JVM instruction being executed.
- Native Method Stack — supports native (JNI) method calls.
- Code Cache — JIT-compiled native code. Bounded by -XX:ReservedCodeCacheSize.
Classloading
// JVM Classloaders — hierarchical delegation model
// 1. Bootstrap ClassLoader — loads core Java (rt.jar / java.base)
// 2. Platform ClassLoader — loads JDK modules (Java 9+)
// 3. Application ClassLoader — loads your application's classpath
// Class loading happens on first use: access static field, create instance, invoke method
// Phases: LOADING → LINKING (Verify + Prepare + Resolve) → INITIALIZATION
public class ClassloadingDemo {
public static void main(String[] args) throws Exception {
// Get the classloader hierarchy
ClassLoader appLoader = ClassloadingDemo.class.getClassLoader();
ClassLoader platformLoader = appLoader.getParent();
ClassLoader bootstrap = platformLoader.getParent(); // null — Bootstrap is native
System.out.println("App: " + appLoader); // jdk.internal.loader.ClassLoaders$AppClassLoader
System.out.println("Platform: " + platformLoader); // jdk.internal.loader.ClassLoaders$PlatformClassLoader
System.out.println("Bootstrap:" + bootstrap); // null
// Load a class explicitly
Class<?> clazz = Class.forName("com.priygop.library.model.Book");
System.out.println("Loaded: " + clazz.getName());
// ClassLoader delegation: child always asks parent first
// If parent can load it → parent loads it
// Only if parent fails → child tries
// Where is a class loaded from?
String location = String.class.getResource("String.class").toString();
System.out.println("String loaded from: " + location);
}
}Quick Quiz
Tip
Tip
Practice JVM Architecture Classloader Memory Areas in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
JVM enables 'Write Once, Run Anywhere' — bytecode runs on any platform
Practice Task
Note
Practice Task — (1) Write a working example of JVM Architecture Classloader Memory Areas from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Common Mistake
Warning
A common mistake with JVM Architecture Classloader Memory Areas is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready java code.
Key Takeaways
- The JVM is a virtual machine that runs Java bytecode.
- Heap — where objects live. Shared by all threads. Divided into Young and Old generations.
- Young Generation (Eden + Survivor spaces S0/S1) — new objects allocated here. Cleared by Minor GC.
- Old Generation (Tenured) — long-lived objects promoted from Young. Cleared by Major/Full GC.