Java Memory Management
1. How Java Program Runs
When you write a .java file and run it:
1. Code → compiled by javac → .class bytecode.
2. JVM loads bytecode into memory.
3. JVM creates different memory areas to manage program execution.
2. JVM Memory Areas
The JVM divides memory into runtime data areas, created when a JVM starts, and destroyed
when it shuts down. These areas manage class loading, object storage, method execution,
and garbage collection.
1. Heap Memory
Location: Shared across all threads
Purpose: Stores all objects and arrays at runtime
• Whenever you use new, the object is created in the heap.
• Each object has:
o Instance variables (object data).
o Reference (in stack) points to it.
• Heap is garbage-collected → objects no longer referenced are cleaned by GC.
Heap Structure (Generational Model)
To optimize GC, heap is split into generations:
1. Young Generation (Eden + Survivor spaces)
o Eden Space → New objects are created here.
o Survivor Spaces (S0, S1) → After surviving GC, objects are copied here.
o If they survive multiple cycles, they get promoted to Old Generation.
2. Old Generation (Tenured)
o Stores long-lived objects.
o Example: Objects in caches, static data structures.
3. Metaspace (Java 8+) / PermGen (Java 7 and below)
o Stores class metadata, method bytecode, static variables.
2. Stack Memory
Location: One stack per thread (private, not shared)
Purpose: Stores method calls and local variables
How it works:
• Each method call creates a Stack Frame (LIFO structure).
• Frame contains:
1. Local Variables → references & primitives.
2. Operand Stack → stores intermediate calculations.
3. Frame Data → return addresses, method info.
When method finishes, its stack frame is popped out.
Example:
• x → directly in stack.
• s → reference in stack, points to "Hello" in heap/string pool.
Stack = fast, but limited in size.
StackOverflowError occurs if recursion goes too deep.
3. Method Area (Metaspace in Java 8+)
Location: Shared across all threads
Purpose: Stores class-level data
• Class bytecode (methods, constructors, static variables).
• Field & method names, access modifiers, constant pool (literals, symbolic
references).
• Static variables & method code.
Difference:
• Java 7 and below: Method Area (PermGen) (fixed size → OutOfMemoryError).
• Java 8+: Metaspace → allocated in native memory, grows dynamically.
Example:
4. Program Counter (PC) Register
Thread-specific (each thread has its own PC register)
Purpose: Keeps track of the next instruction the JVM needs to execute for a given
thread.
How it works:
• When a thread runs Java bytecode, the PC register contains the address of the
current instruction in the JVM’s code.
• After execution, the PC is updated to point to the next instruction.
• This enables multi-threading:
o Each thread has its own PC register.
o The JVM uses the PC to resume execution correctly when switching between
threads.
PC Behavior:
• If executing Java method → PC register contains the address of the JVM instruction.
• If executing a native method (JNI) → PC register is undefined (JVM does not track
native code).
Analogy: The PC register is like a “bookmark” in a book, telling the JVM where each
thread last left off.
5. Native Method Stack
Thread-specific (each thread gets its own)
Purpose: Executes native methods (C, C++, or assembly code) called from Java.
How it works:
• Java supports JNI (Java Native Interface), allowing Java to call native libraries.
• When you invoke a native method, JVM delegates execution to native method stack
(not the Java stack).
• Each thread has:
o Java Stack → for Java methods.
o Native Stack → for native methods.
Example:
Here:
• printHello() → not implemented in Java, but in C/C++.
• JVM creates frames in the native method stack to execute it.
Without native stack → JVM couldn’t integrate with OS APIs or external libraries.
Garbage Collection (GC)
Purpose: Automatically frees memory by removing unreachable objects from the heap.
Key Rules:
• GC runs only on heap (not stack, not method area).
• Stack frames are auto-destroyed when methods return → no need for GC.
GC Steps (Mark-Sweep-Compact):
1. Mark → Traverse the object graph from GC Roots (local variables, static references,
active threads) and mark all reachable objects.
2. Sweep → Delete unmarked objects.
3. Compact → Rearrange live objects to avoid fragmentation.
Generational GC:
Heap is split for efficiency:
• Young Generation (Eden + Survivor) → short-lived objects.
• Old Generation → long-lived objects.
• Metaspace → class metadata (since Java 8).
Example of GC:
• "Hello" becomes unreachable after s = null.
• GC may collect it.
String Pool
Location: Inside heap (in “String Table” managed by JVM).
Purpose: Saves memory by reusing identical string literals.
The String Pool (a.k.a. String Intern Pool, String Table) is a special area in the heap where
JVM stores unique copies of string literals.
• It is implemented as a hash table internally.
• Goal → Avoid duplicate strings, save memory.
• Accessible across all threads (shared).
Location Evolution:
• Java 6 and below → String Pool was inside PermGen (method area) → limited size.
• Java 7+ → Moved to Heap → better GC support.
• Java 8+ → Still in Heap (no PermGen anymore, replaced by Metaspace).
How Strings are Created and Stored
Case 1: String Literals
• "Hello" is stored once in the String Pool.
• Both s1 and s2 point to the same pooled object.
• Saves memory.
Case 2: Using new
. "Hello" (literal) → goes into String Pool if not already present.
. new String("Hello") → creates a new object in the heap (outside the pool).
So now you have two objects:
1. "Hello" in the pool.
2. A new "Hello" in the heap, referenced by s3.
The intern() Method
Definition:
intern() ensures that the string is added to the String Pool, and returns the reference from
the pool.
If the pool already contains an equal string, intern() returns that reference.
If not, it adds the string to the pool and returns it.
Example 1: Basic Intern
Example 2: Dynamic Strings
Example 3: Intern before literal
• "Java" is first interned → added to pool.
• Literal "Java" points to the same reference.
Why intern() is Useful
1. Memory Optimization
o If you create millions of duplicate strings (e.g., XML parsing, JSON keys),
intern() avoids duplicate heap objects.
2. Performance (Comparisons)
o String comparison with == becomes valid if both are interned.
o Normally, == compares references, .equals() compares content.
3. Example Use Case:
Parsing XML with repeated tag names like "id", "name". Without intern(), each
occurrence would create a new object in the heap. With intern(), they all point to
one pooled object.
Caveats of String Pool and intern()
• Too much interning = memory pressure:
o String Pool lives in heap (Java 7+).
o If you intern too many large strings, you can cause OutOfMemoryError: Java
heap space.
• Thread-safety:
o String Pool is thread-safe, but excessive concurrent interning may cause
contention.
• Not always faster:
o Interning has overhead (pool lookup + insertion).
o Good for repeated strings, bad for unique/random strings (like UUIDs).
Internal Implementation (Advanced)
• The String Pool is a HashMap-like table inside JVM.
• When you call intern():
1. JVM computes the hash of the string.
2. Checks if it’s in the pool.
3. If yes → returns reference.
4. If no → inserts it into the pool.
• In OpenJDK, the pool is maintained in a class called StringTable.
Visual Diagram (in words)
Code:
Memory Layout:
Summary (Memory Locations)
Area Thread-Specific? Stores
Stack Yes (per thread) Local variables, method calls, references
Heap Shared Objects, arrays, string pool
Method Area / Metaspace Shared Class metadata, static variables, constant pool
PC Register Yes (per thread) Current instruction
Native Method Stack Yes (per thread) Native method calls
Example:
Step-by-Step Memory Storage
1. Class Loading
When JVM loads MemoryDemo.class:
• Method Area / Metaspace (shared across threads):
o Class metadata (MemoryDemo info, constructor, methods).
o Static variable staticVar = 100.
o String literal "Hello" placed into String Pool (in heap).
2. main() Execution
• A new stack frame for main() is created.
• Inside it:
o localMainVar = 10 → stored in stack (primitive).
o args → reference to String array in heap.
3. Object Creation
• new → allocates memory in heap for obj1.
• instanceVar = 200 stored inside obj1 (heap).
• Reference to obj1 stored in stack (obj1).
Similarly for obj2:
• New object in heap with instanceVar = 300.
• Reference obj2 stored in stack.
4. Calling display()
When obj1.display() is called:
• New stack frame for display() is created.
• Inside frame:
o localString = "Hello" → reference in stack → points to pooled "Hello" in heap.
o localVar = 50 → primitive in stack.
• instanceVar → accessed via obj1 reference → read from heap (200).
Same happens for obj2.display(), but instanceVar = 300.
Visual Diagram (Textual)
Summary by Category
• Static variables → Method Area (Metaspace), one copy for all objects.
• Instance variables → Heap, separate per object.
• Local variables → Stack, destroyed when method ends.
• Methods → Bytecode stored in Method Area; execution creates stack frames.
• String literals → Stored in String Pool (inside heap), shared globally.
• Objects → Heap, referenced by stack variables.
Another Example:
It contains
Local variables (inside methods)
Instance variables (object-level)
Static variables (class-level)
Literals (numbers, strings, chars, etc.)
Methods (instance & static)
How JVM Stores This (Memory Breakdown)
Method Area / MetaSpace (Class Level Info)
• MemoryDemo.class bytecode is loaded here by the ClassLoader.
• Stores metadata about class (methods, fields, constants).
• staticVar, staticString, and CONST references are placed here (but their values live in
heap/string pool).
• Method bytecode for main() and show() also resides here.
Heap Memory (Objects, Instance Variables, String Pool)
• When new MemoryDemo() is called → Heap allocates an object:
• Static variables (staticVar = 100, staticString = "Hello", CONST = 50)
live in Method Area, but their referenced objects ("Hello") live in the String Pool
(inside Heap).
• new String("Hello") → creates a new object in Heap, even though "Hello" is already
in String Pool.
Stack Memory (Per Thread)
When main() is executed:
• A stack frame is created for main().
o Local variable args (reference to command-line arguments array in Heap).
o Reference obj → points to MemoryDemo object in Heap.
When obj.show(10) is called:
• A new stack frame for show() is created:
o param = 10 (method parameter, stored in Stack).
o localVar = 300 (local variable, stored in Stack).
o dynamicString → reference in Stack, pointing to new String("Hello") in Heap.
String Pool (inside Heap, special area)
• "Hello" → stored in String Pool.
• "World" → stored in String Pool.
• staticString and instanceString both reference pooled literals.
• new String("Hello") → creates a separate object in Heap (not pooled).
Garbage Collection (GC)
• If no reference points to an object (e.g., dynamicString goes out of scope after
method finishes),
GC will eventually reclaim it.
• String Pool entries are usually not garbage-collected until the classloader is
unloaded.
Visual Representation
Java Memory Management – Interview Q&A
1. What are the main runtime memory areas in JVM?
Answer:
• Method Area (MetaSpace in Java 8+): Stores class metadata, static variables,
constants, method bytecode.
• Heap: Stores objects, instance variables, arrays, String Pool. Shared across all
threads.
• Stack: Each thread has its own stack. Stores local variables, references, method call
frames.
• PC Register: Stores address of current JVM instruction being executed.
• Native Method Stack: Used for native (non-Java) method execution.
2. Where are local variables, instance variables, and static variables stored?
Answer:
• Local variables: Stored in Stack frames of a method.
• Instance variables: Stored in the Heap, inside the object.
• Static variables: Stored in Method Area (MetaSpace), shared by all objects.
3. What is the difference between Stack and Heap memory?
Answer:
• Stack:
o Stores local variables, references, and method frames.
o Thread-local (each thread has its own).
o Faster and smaller in size.
• Heap:
o Stores objects, arrays, instance variables.
o Shared among all threads.
o Larger and slower compared to Stack.
4. What is Method Area in JVM?
Answer:
• A part of JVM memory that stores:
o Class structure (metadata, method info).
o Static variables.
o Runtime constant pool.
• From Java 8 onwards → replaced by Metaspace, which resides in native memory,
not in JVM heap.
5. What is the PC Register in JVM?
Answer:
• A per-thread small memory that stores the address of the current executing JVM
instruction.
• If the method is native, the PC register is undefined.
6. What is the Native Method Stack?
Answer:
• Special stack for native methods (methods written in C/C++).
• When Java calls System.loadLibrary(), native code execution uses this stack.
7. What is the String Pool?
Answer:
• A special memory area in Heap for storing String literals.
• Ensures that identical String literals point to the same object (memory optimization).
• Example:
8. What does String.intern() do?
Answer:
• intern() ensures the String is in the String Pool.
• If already present → returns pooled reference.
• If not → adds it to the pool.
9. What is the difference between new String("Hello") and "Hello"?
Answer:
• "Hello" → stored in String Pool.
• new String("Hello") → creates a new object in Heap, even if "Hello" exists in the
pool.
10. Where are final, static, and const values stored?
Answer:
• Static variables → Method Area.
• Final constants → stored in constant pool at compile time.
• Literals (e.g., int 10, char 'a') → stored in constant pool.
11. What is Garbage Collection (GC) in Java?
Answer:
• Automatic process of reclaiming memory used by objects no longer referenced.
• JVM decides when to run GC.
• Helps avoid memory leaks but does not guarantee when objects are destroyed.
12. How does Garbage Collector identify unused objects?
Answer:
• Uses reachability analysis (GC Roots).
• If an object is not reachable from GC Roots (stack variables, static references, JNI
references) → it becomes eligible for GC.
13. What are GC Roots in Java?
Answer:
• References considered as roots in memory graph traversal.
• Examples:
o Local variables in stack.
o Active thread references.
o Static fields.
o JNI references.
14. What is the difference between Minor GC and Major GC?
Answer:
• Minor GC: Cleans Young Generation (Eden + Survivor spaces).
• Major/Full GC: Cleans Old Generation + Metaspace (more expensive).
15. What are the generations in Java Heap memory?
Answer:
• Young Generation (Eden + Survivor spaces): Newly created objects.
• Old Generation (Tenured): Long-lived objects.
• Metaspace (Java 8+): Class metadata, method info.
16. What is Stop-the-World in GC?
Answer:
• During some phases of GC, JVM pauses all application threads.
• These pauses are called Stop-the-World events.
17. Can we force Garbage Collection in Java?
Answer:
• We can suggest GC using:
• But JVM is free to ignore the request.
18. What is the difference between final, finally, and finalize()?
Answer:
• final: Keyword for constants, methods (cannot override), classes (cannot extend).
• finally: Block used with try-catch for cleanup code.
• finalize(): A method called by GC before reclaiming an object (deprecated in Java 9).
19. How are Strings stored before and after Java 7?
Answer:
• Before Java 7 → String Pool was inside PermGen (Method Area).
• From Java 7 onwards → String Pool moved to Heap.
• This allows more flexible memory allocation.
20. What is the difference between WeakReference, SoftReference, and
PhantomReference?
Answer:
• Strong Reference (normal): Object never GC’d until reference is null.
• WeakReference: Collected in next GC cycle if no strong references exist.
• SoftReference: Collected only when JVM is running low on memory.
• PhantomReference: Used for tracking object finalization, collected after finalize.
21. What happens if stack memory overflows?
Answer:
• Throws StackOverflowError, usually caused by deep/recursive method calls.
22. What happens if heap memory is exhausted?
Answer:
• JVM throws OutOfMemoryError: Java heap space.
23. Why is String immutable in Java?
Answer:
• Security (e.g., class loading paths).
• Thread-safety (shared String literals).
• Caching (String Pool optimization).
• Allows use in HashMaps as keys.
24. Can an object be GC’d if it is still referenced?
Answer:
• No. Only unreachable objects are eligible for GC.
25. Is Garbage Collection deterministic in Java?
Answer:
• No. We cannot predict when GC will run. JVM decides based on memory pressure.