Memory Management & Garbage Collection
Stack memory stores method calls and local variables — fast, and automatically cleaned up once the method ends.
Heap memory stores objects (created with "new") — they stick around as long as some reference is using them.
The Garbage Collector (GC) automatically finds and removes objects with no remaining references — you never need to manually free memory in Java.
void createObjects() {
Student s = new Student(); // heap par banta hai
} // method khatam -> s ab unreachable -> GC eligibleStack memory method calls aur local variables store karti hai — fast (bas ek pointer move karna hota hai push/pop ke liye), aur method khatam hote hi automatically clean ho jaati hai (koi GC ki zaroorat nahi). Har thread ki apni alag Stack hoti hai.
Heap memory objects store karti hai (jo "new" se banaye jaate hain) — ye lambe samay tak rehti hai, jab tak koi reference use na kare. Heap sab threads ke beech shared hota hai (isliye multithreading mein heap objects ke access ko synchronize karna padta hai).
| Stack | Heap | |
|---|---|---|
| Store karta hai | Method calls, local variables, references | Objects, instance fields |
| Speed | Bahut fast | Thoda slow |
| Size | Chhota, fixed (StackOverflowError ho sakta hai) | Bada, configurable (-Xmx flag se) |
| Thread-specific? | Haan, har thread ki apni | Nahi, sab threads shared |
| Cleanup | Automatic (method return par) | Garbage Collector |
JVM Heap ko generations mein baantta hai kyunki experience se pata chala hai — "most objects die young" (zyadatar objects thodi der mein hi unused ho jaate hain, jaise ek loop ke andar banaya temporary object). Young Generation naye objects ke liye — yaha GC bahut baar chalta hai, fast hota hai (kyunki chhota area scan karna hai).
Jo objects lambe samay tak zinda rehte hain (kayi GC cycles survive kar lete hain), wo Old Generation (Tenured) mein promote ho jaate hain — yaha GC kam baar chalta hai, thoda slower (bada area, lekin rarely chalta hai).
Serial GC: single-threaded, chhoti applications/single-core machines ke liye — simple lekin pause times bade ho sakte hain.
Parallel GC: multiple threads use karta hai GC ke liye, throughput-focused (total work jaldi khatam karna, pause times ki utni parwaah nahi).
G1 (Garbage First): modern default (Java 9+), Heap ko chhote regions mein baantta hai aur predictable, chhote pause times deta hai — bade applications ke liye best, especially jaha response time matter karta hai.
Automatic GC hone ke bawajood memory leaks ho sakte hain: (1) static collections mein objects add karte jaana bina kabhi remove kiye (jaise ek static List jo kabhi khaali nahi hoti) — static references JVM ke poore lifetime tak "reachable" rehte hain.
(2) unclosed resources (files, database connections) jo GC clean nahi karta (GC sirf memory manage karta hai, external resources nahi) — isiliye try-with-resources zaroori hai. (3) listeners/callbacks jo register hue hain lekin kabhi unregister nahi hue — inn saare cases mein objects "reachable" reh jaate hain, isliye GC unhe hata nahi sakta, chahe practically wo "unused" hi ho.
Purane Java mein finalize() method tha jo object garbage collect hone se pehle chalta tha cleanup ke liye — lekin ye unpredictable tha (pata nahi kab chalega, kabhi chale hi na, GC ka control tha) isliye Java 9+ mein deprecated ho gaya aur Java 18 mein completely remove hone ki taiyari mein hai.
Modern approach: AutoCloseable interface + try-with-resources use karo, jo deterministic (guaranteed, turant, predictable time par) cleanup deta hai — file/connection band karne jaisi cheezon ke liye ye hi sahi tarika hai.