Understanding JVM Memory Management
1. Understanding Memory Areas
| Area | Purpose |
|---|---|
| Heap | Objects, arrays |
| Metaspace | Class metadata (off-heap, since Java 8) |
| Stack | Per-thread frames, locals |
| PC Register | Per-thread instruction pointer |
| Native Method Stack | JNI frames |
| Code Cache | JIT-compiled native code |
| Direct buffers | Off-heap NIO memory |
2. Understanding Heap Structure
Heap Layout (Generational GC)
+----------------------- Heap -----------------------+
| Young Gen | Old Gen (Tenured) |
| Eden | Survivor 0 | S 1 | long-lived objects |
+----------------------------+-----------------------+
| Region | Use |
|---|---|
| Eden | New allocations |
| Survivor 0/1 | Survived 1+ minor GC |
| Old Gen | Promoted long-lived |
3. Understanding Young Generation
| Aspect | Detail |
|---|---|
| Minor GC | Collects Young only — fast (copying) |
| Survivor copy | Eden+S0 → S1 (or vice versa) |
| Tenuring threshold | -XX:MaxTenuringThreshold |
4. Understanding Object Allocation (TLAB)
| Concept | Detail |
|---|---|
| TLAB | Thread-Local Allocation Buffer in Eden |
| Bump pointer | O(1) allocation, no contention |
| Resize | Adaptive (-XX:+ResizeTLAB) |
| Slow path | Refill or allocate in shared Eden |
5. Understanding Object Promotion
| Trigger | Detail |
|---|---|
| Age threshold | Survived N copy cycles |
| Survivor full | Promote early |
| Premature promotion | Bad for GC pause times |
6. Using Memory Flags (-Xms, -Xmx, -XX:MetaspaceSize)
| Flag | Use |
|---|---|
-Xms | Initial heap |
-Xmx | Max heap |
-Xss | Stack size per thread |
-XX:MetaspaceSize | Initial metaspace |
-XX:MaxMetaspaceSize | Cap metaspace |
-XX:MaxDirectMemorySize | Direct ByteBuffer cap |
7. Understanding Escape Analysis
| Result | Optimization |
|---|---|
| No escape | Scalar replacement / stack allocation |
| Method-only escape | Lock elision |
| Global escape | No optimization |
| Flag | -XX:+DoEscapeAnalysis (default on) |
8. Understanding Native Memory (off-heap)
| Source | Detail |
|---|---|
| DirectByteBuffer | NIO; counts against MaxDirectMemorySize |
| Foreign Memory API | Java 22+ replacement for Unsafe |
| JNI mallocs | Outside JVM accounting |
| Tracking | Native Memory Tracking (-XX:NativeMemoryTracking=summary) |
9. Understanding String Interning
| Aspect | Detail |
|---|---|
| Storage | String table in main heap (Java 7+) |
str.intern() | Returns canonical instance |
| Sizing | -XX:StringTableSize |
| Stats | jcmd VM.stringtable |
10. Using Compressed OOPs (-XX:+UseCompressedOops)
| Aspect | Detail |
|---|---|
| Default | On for heaps ≤ ~32 GB |
| Effect | 32-bit refs in 64-bit JVM (3-bit shift) |
| Disable | -XX:-UseCompressedOops for huge heaps |
| Class pointers | -XX:+UseCompressedClassPointers |
11. Monitoring Memory Usage
| Tool | Use |
|---|---|
| jcmd PID GC.heap_info | Quick heap stats |
| jstat -gc PID 1s | Live GC counters |
| JMX MemoryMXBean | Programmatic |
| JFR / Mission Control | Recording-based |
12. Detecting Memory Leaks
Leak-Hunting Workflow
- Reproduce growing usage with
-Xlog:gc* - Trigger heap dump:
jcmd PID GC.heap_dump heap.hprof - Open in Eclipse MAT — check Dominator Tree, Leak Suspects
- Identify retained-by chain (often static caches, ThreadLocals)
- Patch and verify with regression heap dump
| Common Cause | Fix |
|---|---|
| Static collections | Use WeakHashMap or LRU cache |
| ThreadLocal in pools | Always remove() on exit |
| Listeners not unregistered | Symmetric add/remove |
| ClassLoader leaks | Common in app servers — release on undeploy |