Memory Management और Garbage Collection
Stack memory method calls और local variables store करती है — fast, और method ख़त्म होते ही automatically clean हो जाती है।
Heap memory objects store करती है (जो "new" से बनाए जाते हैं) — ये लंबे समय तक रहती है, जब तक कोई reference use ना करे।
Garbage Collector (GC) automatically उन objects को ढूँढ कर हटा देता है जिनकी कोई reference नहीं बची — Java में manually memory free करने की ज़रूरत नहीं पड़ती।
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.