JVM Fundamentals: Architecture, Class Loading, Memory Management, and Garbage Collection
This article provides a comprehensive overview of the Java Virtual Machine, covering its cross‑platform nature, core components, class‑loader mechanisms, memory layout, object creation steps, various garbage‑collection algorithms and collectors, as well as common interview questions and answers.
1. JVM Basics
1) How does Java achieve cross‑platform?
Note: The cross‑platform feature belongs to Java programs, not the JVM. The JVM itself is written in C/C++ and compiled to native code for each platform.
Answer: Java source files are compiled into .class bytecode. The JVM loads this bytecode and translates it into machine code for the underlying OS. By installing the appropriate JVM on each platform, the same bytecode runs everywhere, achieving "write once, run anywhere".
2) What is the JVM?
Answer: The Java Virtual Machine (JVM) simulates a computer to execute Java bytecode. It abstracts away hardware and OS differences, allowing the same bytecode to run on any architecture.
3) What are the main components of the JVM?
The JVM consists of four parts:
Class Loader – loads required .class files.
Execution Engine – executes bytecode instructions, analogous to a CPU.
Memory Areas – divides memory into regions (method area, heap, stack, etc.) to store class metadata, objects, and execution frames.
Native Method Interface – invokes native C/C++ code.
4) What is a Class Loader?
Answer: A class loader reads .class files and creates java.lang.Class objects. It can load classes from the file system, network, or generated dynamically. Two classes are considered the same only if both their fully qualified names and the class loaders that loaded them are identical.
5) How does a Class Loader load a class?
The loading process includes three stages:
Loading – locate the binary data and read it into memory.
Linking – consists of verification, preparation (allocating memory for static fields), and resolution (converting symbolic references to direct references).
Initialization – execute static initializers and assign explicit static values.
6) Parent‑Delegation Model
Class loaders form a hierarchy with the Bootstrap class loader at the top. When a class is requested, the current loader first checks its cache, then delegates to its parent, and finally loads the class itself if none of the ancestors have loaded it.
2. JVM Memory Management
1) JVM Memory Layout
The JVM divides memory into several regions:
Method Area (shared) – stores class metadata, static variables, and JIT‑compiled code.
Heap (shared) – the main area for object allocation, managed by garbage collectors. It is further split into Young Generation (Eden + Survivor spaces) and Old Generation.
Thread‑Local Stack – stores frames, local variables, operand stacks, and return addresses.
Program Counter (PC) Register – per‑thread pointer to the next bytecode instruction.
Native Method Stack – supports execution of native (C/C++) methods.
2) Object Allocation Rules
Objects are allocated in Eden first; if Eden is full, a Minor GC occurs. Large objects may be allocated directly in the Old Generation. Objects that survive multiple GCs are promoted based on age thresholds and space‑guarantee policies.
3) Java Memory Model (JMM)
All variables reside in main memory, while each thread has its own working memory (a copy of needed variables). Reads and writes must go through main memory, and thread communication occurs via this shared main memory.
4) Memory Barriers
Memory barriers are processor instructions that enforce ordering constraints on memory operations, preventing harmful re‑ordering in multi‑threaded environments.
5) JVM Parameters (-Xms, -Xmx, -Xmn, etc.)
• -Xms : initial heap size. • -Xmx : maximum heap size. • -Xmn : size of the Young Generation. • -XX:SurvivorRatio : ratio between Eden and Survivor spaces. • -XX:PermSize / -XX:MaxPermSize : initial and maximum non‑heap (PermGen) sizes (pre‑Java 8).
6) Memory Leak vs. Out‑Of‑Memory
Memory leak: objects remain reachable but are no longer needed, preventing GC. Out‑Of‑Memory: the JVM cannot allocate more memory because the heap is exhausted.
7) Object Creation Process
Check if the class is already loaded; if not, trigger class loading.
Allocate memory in the heap (pointer bump or free‑list).
Zero‑initialize the allocated memory.
Set object header information (class pointer, hash code, GC age, lock bits).
Invoke the <init> method to run constructor code.
3. Garbage Collection (GC)
1) How to determine if an object is dead?
Two methods are used:
Reference counting – simple but cannot handle cyclic references.
Reachability analysis – start from GC roots and mark all reachable objects; unmarked objects are considered dead.
2) GC Algorithms
Reference Counting
Mark‑Sweep
Copying (used for Young Generation)
Mark‑Compact (used for Old Generation)
Generational Collection – combines different algorithms for Young and Old generations.
3) When does GC start?
Minor GC occurs when Eden is full; Full GC occurs when the Old Generation lacks space or when certain promotion thresholds are exceeded.
4) Types of References
Strong – prevents collection.
Soft – collected before an Out‑Of‑Memory error.
Weak – collected on the next GC cycle.
Phantom – used to receive notification after an object is reclaimed.
5) Garbage Collectors
Common collectors and their typical JVM flags:
Serial – -XX:+UseSerialGC
ParNew – -XX:+UseParNewGC
Parallel Scavenge – -XX:+UseParallelGC
Parallel Old – -XX:+UseParallelOldGC
CMS – -XX:+UseConcMarkSweepGC
G1 – -XX:+UseG1GC
4. Additional JVM Interview Questions
1) Size of int on 64‑bit JVM
Always 32 bits (4 bytes), independent of the underlying platform.
2) Determine JVM bitness from Java code
System property sun.arch.data.model returns "32" or "64".
System.getProperty("sun.arch.data.model")3) Maximum heap size on 32‑bit vs 64‑bit JVM
32‑bit JVM is limited to roughly 1.5‑3 GB depending on OS; 64‑bit JVM can be configured to tens or hundreds of gigabytes.
4) Can you force a GC?
Calling System.gc() or Runtime.gc() only suggests a collection; execution is not guaranteed.
5) Retrieve memory usage
Use Runtime.totalMemory() , Runtime.freeMemory() , and Runtime.maxMemory() to compute heap usage and percentages.
6) Difference between heap and stack
The heap stores objects shared among threads; the stack stores method frames and local primitives for each thread.
All questions and answers are compiled for reference only; errors are welcome for correction.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
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.