■ JVM Internals, Memory Model & Garbage CollectionSenior / Principal Java Engineer – Complete Interview Master GuideHotSpot Architecture · Heap & Non-Heap · Class Loading · JIT · JMM · All GC Algorithms up to Java 21
| Prepared for | Ashok Koritala – Senior Java Full Stack Developer (15+ yrs) |
| Java Version | Covers Java 8 through Java 21 (LTS) |
| Total Questions | 45 expert-level Q&A; across 9 topic clusters |
| Topics | JVM architecture · Runtime data areas · Class loading · JIT · JMM · Serial/Parallel/CMS/G1/ZGC/Shenandoah · GC tuning · Virtual Threads |
| ■ Key Insight: The JVM spec defines behaviour; HotSpot is one implementation. Others include GraalVM, OpenJ9, AzulZing. Always clarify 'HotSpot' in interviews. |
| ■ Interview Tip: Draw a box diagram: ClassLoader → Runtime Data Areas (Heap/Non-Heap) → Execution Engine(Interpreter + JIT + GC). Interviewers love this visual. |
| Area | Scope | GC'd? | OOM Possible? | Key Flags |
| Heap | All threads | Yes | Yes | -Xms -Xmx |
| Metaspace | All threads | Partial | Yes | -XX:MaxMetaspaceSize |
| JVM Stack | Per-thread | No | SOE/OOM | -Xss |
| PC Register | Per-thread | No | No | – |
| Native Stack | Per-thread | No | OOM | -Xss |
| ■■ Watch Out: PermGen was replaced by Metaspace in Java 8. java.lang.OutOfMemoryError: PermGen space no longer exists. New error: OutOfMemoryError: Metaspace. |
| Action | Description |
| lock | Acquire a monitor (enter synchronized block/method) |
| unlock | Release a monitor (exit synchronized block/method) |
| volatile read | Read of a volatile-declared field |
| volatile write | Write to a volatile-declared field |
| thread start | Thread.start() – HB all actions in the new thread |
| thread join | Thread.join() – all thread actions HB join() return |
| final field write | Constructor write of final field (freeze action) |
| normal read/write | Ordinary reads/writes – no cross-thread guarantee |
| ■ Interview Tip: When asked 'what guarantees does synchronized give?', walk through unlock HB lock and the visibilityflush that entails. |
| Construct | Visibility | Atomicity | Mutual Excl. | Overhead | Best For |
| volatile | Yes | Single R/W only | No | Very low | Flags, status fields |
| AtomicInteger | Yes | CAS compound ops | No (lock-free) | Low | Counters, CAS patterns |
| synchronized | Yes | Yes (block) | Yes | Medium | Multi-var invariants |
| ReentrantLock | Yes | Yes (block) | Yes | Medium | tryLock, conditions, fair queue |
| LongAdder | Yes | Yes (striped) | No | Very low | High-throughput counters |
| StampedLock | Yes | Yes | Yes | Low (opt.read) | Read-heavy, non-reentrant |
| ■ Interview Tip: LongAdder vs AtomicLong: under high contention, LongAdder is 10–20x faster. Use AtomicLong whenyou need current value frequently; LongAdder when you only need sum at the end. |
| GC | STW Phases | Typical Max Pause |
| Serial / Parallel | All phases STW | 100ms – seconds |
| CMS | Initial+Remark STW | 10–200ms |
| G1 | Initial+Remark+Cleanup | 5–200ms (target configurable) |
| ZGC (Java 11–20) | Initial+Final mark+Relocate roots | <1ms – ~10ms |
| ZGC (Java 21 Gen) | Per-generation roots | Sub-millisecond |
| Shenandoah | Initial+Final mark+Roots | <10ms |
| Feature | ZGC | Shenandoah |
| Barrier type | Load barrier (reference check) | Write barrier (store intercept) |
| Concurrent relocation | Yes (coloured pointers) | Yes (forwarding pointers) |
| Heap size | Up to 16 TB | Up to tested TBs |
| Memory overhead | Moderate (coloured ptr bits) | Slightly higher (fwd pointer/obj) |
| Generational (Java 21) | Yes (ZGenerational, default soon) | Experimental |
| Pause target | Sub-millisecond | Sub-10ms typical |
| Best for | Latency-critical, large heap | Latency-critical, memory constrained |
| Flag | Default | Purpose |
| -Xms / -Xmx | 1/4 RAM / 1/4 RAM | Min/max heap size. Set equal in production to avoid resize pauses. |
| -Xss | 512k–1m | Thread stack size. Reduce for many threads. |
| -XX:NewRatio=N | 2 | Old:Young ratio. NewRatio=2 → Young=1/3 of heap. |
| -XX:SurvivorRatio=N | 8 | Eden:Survivor ratio. 8 → Eden=8/10 of Young. |
| -XX:MaxTenuringThreshold=N | 15 | GC cycles before promotion to Old Gen. |
| -XX:MaxGCPauseMillis=N | 200 | G1/ZGC pause target (soft goal). |
| -XX:+UseStringDeduplication | off | G1: deduplicate identical Strings (reduce heap). |
| -XX:+DisableExplicitGC | off | Ignore System.gc() calls. |
| -XX:+AlwaysPreTouch | off | Pre-allocate heap pages at JVM start (reduce latency spikes). |
| -XX:+UseCompressedOops | on (<32GB) | Use 32-bit object pointers (saves ~20% memory). |
| Aspect | ThreadLocal | ScopedValue (Java 21) |
| Mutability | Mutable (set/get/remove) | Immutable within scope |
| Cleanup | Manual remove() required | Auto-cleaned on scope exit |
| Inheritance | Manual (InheritableThreadLocal) | Automatic for child VTs |
| Memory | Per-thread hash map (leaks) | Stack-like scope, no leak |
| Performance | Hash map lookup O(1) amortised | Faster (no map overhead) |
| Best for | Legacy / mutable per-thread data | Request context, user ID, MDC |
| Java | JEP/Feature | Impact on JVM/GC |
| 8 | Metaspace replaces PermGen | Eliminates PermGen OOM; native memory growth |
| 8 | G1 GC (not yet default) | Region-based, pause targets |
| 9 | G1 becomes default GC | Better balanced throughput/latency |
| 9 | Compact Strings | Latin-1 Strings use byte[] not char[] – 50% memory saving |
| 9 | JPMS (Jigsaw) | Modular ClassLoader hierarchy |
| 10 | Parallel Full GC for G1 | Reduces G1 Full GC pause |
| 10 | Container-aware heap sizing | Reads cgroup limits in Docker/K8s |
| 11 | ZGC (experimental) | Sub-millisecond pauses |
| 12 | Shenandoah GC | Low-latency alternative to ZGC |
| 13 | ZGC: uncommit unused memory | Returns heap to OS dynamically |
| 14 | CMS GC removed | G1/ZGC are successors |
| 15 | ZGC production-ready | Sub-ms at scale |
| 15 | Biased locking disabled (JEP 374) | Simplification; removed Java 21 |
| 16 | Elastic Metaspace (JEP 387) | Returns metaspace to OS promptly |
| 17 | Unified logging improvements | Better GC log tooling |
| 21 | Generational ZGC (JEP 439) | Best-of-both: ZGC + generational |
| 21 | Virtual Threads GA (JEP 444) | Heap-allocated stacks; GC-aware |
| 21 | ScopedValues Preview (JEP 446) | Replace ThreadLocal for VTs |
| Heap → Young (Eden+S0+S1) + Old | All objects; GC'd; -Xms/-Xmx |
| Metaspace (Java 8+) | Class metadata; native memory; -XX:MaxMetaspaceSize |
| JVM Stack | Per-thread frames; local vars + operand stack; -Xss |
| Serial GC (-XX:+UseSerialGC) | Single-thread; small heaps; embedded |
| Parallel GC (Java 8 default) | Multi-thread STW; throughput-oriented |
| CMS (removed Java 14) | Concurrent sweep; no compaction; fragmentation risk |
| G1 GC (Java 9+ default) | Region-based; pause targets; balanced; -XX:MaxGCPauseMillis |
| ZGC (Java 15+ production) | Sub-ms pauses; coloured pointers; load barriers; 16TB heap |
| Generational ZGC (Java 21) | -XX:+UseZGC -XX:+ZGenerational; best latency+throughput |
| Shenandoah | Concurrent relocation; forwarding pointers; Red Hat |
| Epsilon GC | No-op GC; testing/short-lived processes only |
| TLAB | Per-thread Eden slice; lock-free bump-ptr allocation |
| Compressed OOPs | 32-bit refs on 64-bit JVM (<32GB heap); saves ~20% memory |
| Escape Analysis + Stack Alloc | JIT: non-escaping objects on stack; no GC pressure |
| Safepoint | All threads paused; STW GC; watch TTSP in logs |
| volatile | Visibility + ordering; NOT mutual exclusion or compound ops |
| synchronized | Mutex + visibility; unlock HB lock; intrinsic monitor |
| Happens-Before (8 rules) | Program order, monitor, volatile, start, join, interrupt, finalizer, transitivity |
| VarHandle (Java 9) | Type-safe acquire/release/volatile access; replaces Unsafe |
| Virtual Threads (Java 21) | Heap stacks; park not block; millions of threads |