Interview
JVM Internals & GC — Interview Questions (120+)
Detailed Questions
1. What are the JVM runtime data areas?
- Short: Heap, Stacks, Metaspace, PC registers, native stacks.
- Detailed: Heap (shared, objects/arrays, GC-managed), JVM Stack (per-thread frames), Metaspace (class metadata in native memory), PC register (per-thread instruction pointer), native method stack (JNI).
- Example: Local
intlives on the stack;new Object()lives on the heap.
2. Stack vs heap?
- Short: Stack = per-thread frames (locals); heap = shared objects.
- Detailed: Stack stores method frames, primitive locals, and references; it's fast and auto-freed on return (LIFO). Heap holds all objects, is shared across threads, and is reclaimed by GC.
- Example: Deep recursion → StackOverflowError; too many objects → OutOfMemoryError (heap).
3. What replaced PermGen and why?
- Short: Metaspace (Java 8); PermGen had fixed size and caused OOM.
- Detailed: Class metadata moved from heap PermGen to native-memory Metaspace, which grows dynamically (bounded by
-XX:MaxMetaspaceSize), reducingOutOfMemoryError: PermGen. - Example: Many dynamically generated classes used to exhaust PermGen.
4. Explain the class loading process.
- Short: Loading → Linking (Verify/Prepare/Resolve) → Initialization.
- Detailed: Load reads bytecode; Verify checks safety; Prepare allocates static fields with defaults; Resolve turns symbolic refs into direct; Initialize runs static initializers (once, on first active use).
- Example: Accessing a static field triggers class init.
5. Describe the class loader delegation model.
- Short: Parent-first: Bootstrap → Platform → Application.
- Detailed: Each loader asks its parent before loading itself, preventing core classes from being overridden by user code (security). Bootstrap loads
java.*(shown as null). - Example:
String.class.getClassLoader()is null (bootstrap).
6. How does garbage collection decide what to collect?
- Short: Reachability from GC roots.
- Detailed: Objects reachable from roots (stack locals, statics, JNI refs, active threads) are live; everything else is garbage. GC marks live, then sweeps/compacts dead.
- Example: Setting the only reference to null makes an object eligible.
7. What is the generational hypothesis?
- Short: Most objects die young.
- Detailed: Heap splits into Young (Eden + Survivors) and Old. Minor GC collects Young frequently and cheaply; survivors are promoted to Old, collected rarely by expensive major/full GC.
- Example: Short-lived request objects die in Eden.
8. Compare G1, ZGC, and Shenandoah.
- Short: G1 = balanced default; ZGC/Shenandoah = ultra-low pause.
- Detailed: G1 is region-based with targetable pauses (
MaxGCPauseMillis), good general default. ZGC does almost everything concurrently using colored pointers/load barriers, sub-millisecond pauses independent of heap size (to multi-TB). Shenandoah does concurrent compaction so pauses don't grow with heap. - Example: Low-latency trading service → ZGC; batch ETL → Parallel.
9. What is a stop-the-world pause?
- Short: GC phase where app threads are paused.
- Detailed: Some GC work needs a consistent snapshot; STW pauses all application threads. Modern collectors minimize STW by doing marking/compaction concurrently.
- Example: Long Full GC pause causes latency spikes.
10. What are the reference types?
- Short: Strong, Soft, Weak, Phantom.
- Detailed: Strong = never collected while reachable. Soft = collected under memory pressure (caches). Weak = collected at next GC if only weakly reachable (
WeakHashMap). Phantom = enqueued after collection for cleanup (Cleaner). - Example: Cache values via SoftReference; metadata via WeakHashMap.
11. Does System.gc() force GC?
- Short: No, it's only a hint.
- Detailed: The JVM may ignore it. Relying on it is an anti-pattern; can be disabled with
-XX:+DisableExplicitGC. - Example: Tests sometimes call it but it's not guaranteed.
12. What is JIT compilation?
- Short: Runtime compilation of hot bytecode to native code.
- Detailed: HotSpot interprets first, profiles, then JIT-compiles hot methods (C1 client, C2 server; tiered). Optimizations: inlining, escape analysis, loop unrolling, dead-code elimination.
- Example: A loop runs faster after it becomes "hot".
13. What is escape analysis?
- Short: Determines if an object escapes a method; may allocate on stack/eliminate.
- Detailed: If an object never escapes, the JIT can scalar-replace it (no heap allocation) and remove synchronization (lock elision).
- Example: A short-lived local object may avoid heap allocation.
14. How do you diagnose a memory leak?
- Short: Heap dump + analyze dominators/retained sizes.
- Detailed: Use
-XX:+HeapDumpOnOutOfMemoryError,jmap/jcmdfor dumps, and Eclipse MAT/VisualVM to find growing retained sets (often static collections, caches, ThreadLocals, listeners). - Example: A static
Listthat only grows.
15. Common JVM tuning flags?
- Short: -Xms/-Xmx, -Xss, GC selection, logging.
- Detailed:
-Xms/-Xmx(heap),-Xss(stack),-XX:+UseG1GC/ZGC/ShenandoahGC,-XX:MaxGCPauseMillis,-Xlog:gc*,-XX:+HeapDumpOnOutOfMemoryError. - Example:
java -Xms2g -Xmx2g -XX:+UseZGC App.
Rapid-Fire (Q → A)
- Bytecode file extension? → .class.
- Who executes bytecode? → JVM.
- JIT stands for? → Just-In-Time compiler.
- AOT in Java? → Ahead-of-time (jaotc/GraalVM native image).
- Interpreter role? → Run bytecode immediately.
- C1 vs C2? → Client (fast compile) vs server (deep opt).
- Tiered compilation? → Mix interpreter + C1 + C2.
- Where do objects live? → Heap.
- Where do locals live? → Stack frame.
- Where do statics live? → Metaspace (with class).
- Where do string literals live? → String pool (heap).
- Young gen parts? → Eden + 2 Survivors.
- Old gen aka? → Tenured.
- Minor GC collects? → Young gen.
- Major/Full GC collects? → Old/whole heap.
- Promotion? → Survivor → Old after threshold.
- TLAB? → Thread-Local Allocation Buffer.
- Default GC (Java 9+)? → G1.
- Throughput GC? → Parallel.
- Lowest latency GC? → ZGC/Shenandoah.
- Serial GC use? → Small heaps/single core.
- G1 region size? → Power-of-two, 1–32MB.
- Humongous object? → Spans ≥ half a region.
- ZGC pointer trick? → Colored pointers.
- ZGC barrier? → Load barrier.
- Shenandoah barrier? → Load-reference barrier.
- STW means? → Stop-the-world.
- GC roots examples? → Stack locals, statics, JNI, threads.
- Reachability? → Path from a root.
- Finalize status? → Deprecated.
- Cleaner? → Modern post-mortem cleanup.
- PhantomReference use? → Cleanup notification.
- WeakHashMap use? → Auto-evicting cache by key.
- SoftReference use? → Memory-sensitive cache.
- OutOfMemoryError types? → Heap, Metaspace, GC overhead, direct buffer.
- GC overhead limit? → Too much time in GC, little reclaimed.
- StackOverflowError cause? → Deep recursion.
- -Xss controls? → Thread stack size.
- -Xmx controls? → Max heap.
- -Xms controls? → Initial heap.
- Set them equal? → Avoids resizing pauses.
- MetaspaceSize flag? → -XX:MaxMetaspaceSize.
- GC logging flag? → -Xlog:gc*.
- Heap dump on OOM? → -XX:+HeapDumpOnOutOfMemoryError.
- Thread dump tool? → jstack.
- Heap dump tool? → jmap/jcmd.
- GC stats tool? → jstat.
- Profiler? → JFR/VisualVM/async-profiler.
- jps? → List JVM processes.
- jcmd? → Diagnostic commands.
- JFR? → Java Flight Recorder.
- Class init trigger? → First active use.
- Static block runs? → Once at init.
- Lazy class loading? → Loaded when needed.
- Bootstrap loader loads? → java.* core.
- Platform loader loads? → JDK modules.
- App loader loads? → Classpath classes.
- Custom class loader use? → Plugins, hot reload.
- Parent-first benefit? → Security/consistency.
- ClassNotFoundException? → Missing at runtime lookup.
- NoClassDefFoundError? → Present at compile, missing at runtime.
- UnsatisfiedLinkError? → Missing native lib.
- Verify phase? → Bytecode safety check.
- Prepare phase? → Static defaults allocated.
- Resolve phase? → Symbolic → direct refs.
- Method area now? → Metaspace.
- Constant pool? → Per-class symbol table.
- String dedup? → G1 feature to share char arrays.
- Compressed oops? → 32-bit refs on 64-bit heaps < 32GB.
- Why heap < 32GB matters? → Keeps compressed oops.
- Object header size? → ~12–16 bytes.
- Object alignment? → 8-byte boundaries.
- Escape analysis benefit? → Stack allocation/lock elision.
- Scalar replacement? → Replace object with its fields.
- Lock elision? → Remove unneeded sync.
- Inlining? → Replace call with body.
- Deoptimization? → Revert JIT assumptions.
- Safepoint? → Where threads can pause for GC.
- Card table? → Tracks old→young refs.
- Remembered set? → Region cross-references (G1).
- Write barrier? → Records reference writes.
- Concurrent marking? → Mark live without full STW.
- Mixed GC (G1)? → Young + some old regions.
- Evacuation? → Copy live objects to new region.
- Fragmentation fix? → Compaction.
- Direct memory? → Off-heap (NIO ByteBuffer).
- -XX:MaxDirectMemorySize? → Caps direct buffers.
- GC tuning first step? → Measure with logs.
- Latency vs throughput? → Pause time vs work done.
- Allocation rate impact? → Higher → more GC.
- Large heap GC choice? → ZGC/Shenandoah.
- Batch job GC choice? → Parallel.
- Default pause target G1? → 200ms.
- Survivor ratio? → Eden:Survivor sizing.
- Tenuring threshold? → Age to promote.
- Premature promotion? → Survivors too small.
- Memory leak signs? → Growing old gen, frequent full GC.
- ThreadLocal leak fix? → remove() after use.
- Static cache leak fix? → Bounded cache/weak refs.
- Native memory leak? → Direct buffers/JNI.
- -verbose:class? → Log class loading.
- -XX:+PrintFlagsFinal? → Dump all flags.
- GraalVM benefit? → Native images, polyglot.
- Native image trade-off? → Fast startup, limited reflection.
- CDS? → Class Data Sharing (faster startup).
- AppCDS? → App-level CDS.
- JIT vs AOT? → Runtime opt vs precompiled.
- Why interpret first? → Fast startup before profiling.
- Hot method? → Frequently executed → JIT'd.
- Tier 4? → C2 fully optimized.
- Bytecode verification importance? → Security/safety.
- Reflection cost? → Slower, bypasses checks.
- MethodHandle? → Faster reflective invocation.
- invokedynamic use? → Lambdas, string concat.
- String concat (Java 9+)? → invokedynamic-based.
- Metaspace OOM cause? → Too many classes/classloaders.
- Classloader leak? → Retained loader keeps classes.
- PhantomReference vs finalize? → Deterministic cleanup queue.
- GC ergonomics? → JVM auto-tunes defaults.
- First GC tuning rule? → Don't tune prematurely; measure.