गार्बेज कलेक्शन के माध्यम से स्वचालित मेमोरी प्रबंधन Android प्लेटफ़ॉर्म का एक प्रमुख तंत्र है, जो ART वर्चुअल मशीन पर आधारित है। Google Android Documentation, 2026 के अनुसार, गार्बेज कलेक्टर डेवलपर को मैनुअल मेमोरी प्रबंधन से मुक्त करता है, स्वचालित रूप से उन ऑब्जेक्ट्स को हटाकर जिनके कोई संदर्भ नहीं बचे हैं। GC के बिना, प्रत्येक ऑब्जेक्ट आवंटन के लिए स्पष्ट रूप से free या delete कॉल की आवश्यकता होती, जो प्रति सेकंड लाखों ऑब्जेक्ट्स वाले Java इकोसिस्टम में शारीरिक रूप से असंभव है।
मुख्य बिंदु
Garbage Collection (GC) उन ऑब्जेक्ट्स द्वारा घेरी गई मेमोरी का पता लगाने और मुक्त करने की एक स्वचालित प्रक्रिया है जो प्रोग्राम द्वारा अब उपयोग नहीं किए जाते हैं। मोबाइल डेवलपमेंट के संदर्भ में, GC का उपयोग Android प्लेटफ़ॉर्म पर ART वर्चुअल मशीन के माध्यम से, साथ ही मानक Java Virtual Machine में किया जाता है।
मैनुअल मेमोरी प्रबंधन वाली भाषाओं (C, C++) के विपरीत, जहाँ प्रोग्रामर को स्पष्ट रूप से free या delete कॉल करना होता है, GC पूरी तरह से ऑब्जेक्ट जीवनचक्र पर नज़र रखने का कार्य लेता है। डेवलपर new ऑपरेटर के माध्यम से नए ऑब्जेक्ट बनाता है, जबकि कलेक्टर यह निर्धारित करता है कि ऑब्जेक्ट कब अप्राप्य हो जाता है — अर्थात उसके पास कोई सक्रिय संदर्भ नहीं बचा है।
मुख्य मीट्रिक GC दक्षता के पॉज़ टाइम (pause time) और थ्रूपुट (throughput) हैं। पॉज़ वह अवधि है जिसके दौरान कलेक्शन के लिए एप्लिकेशन निष्पादन रोका जाता है। मोबाइल वातावरण में, 8–16 मिलीसेकंड से अधिक लंबे पॉज़ छूटे हुए फ्रेम (jank) के रूप में ध्यान देने योग्य होते हैं।
Google I/O 2019 के अनुसार, Android 10 में ART ने विशिष्ट GC पॉज़ को 2–4 ms तक कम कर दिया, जो Android 4.4 में Dalvik की तुलना में 70% कम है। फिर भी, अनुचित मेमोरी प्रबंधन — लूप में बार-बार ऑब्जेक्ट आवंटन, बिना आवश्यकता के अस्थायी इंस्टेंस बनाना — प्रदर्शन समस्याओं का मुख्य कारण बना हुआ है।
Java और Android में GC के सभी कार्यान्वयन कई मौलिक एल्गोरिदम पर आधारित हैं जो पॉज़ समय और संग्रह की संपूर्णता के बीच संतुलन प्राप्त करने के लिए संयुक्त होते हैं। इन एल्गोरिदम को समझना GC-अनुकूल कोड लिखने के लिए आवश्यक है।
Mark-and-Sweep सबसे सरल एल्गोरिदम है, जो दो चरणों में काम करता है। Mark चरण में, कलेक्टर रूट संदर्भों (root set) — स्थानीय चर, स्थैतिक फ़ील्ड, थ्रेड स्टैक — से शुरू करके ऑब्जेक्ट ग्राफ़ को ट्रैवर्स करता है। प्रत्येक सुलभ ऑब्जेक्ट पर जीवित (live) फ़्लैग लगाया जाता है। Sweep चरण में, कलेक्टर पूरे हीप को स्कैन करता है और अचिह्नित ऑब्जेक्ट्स की मेमोरी मुक्त करता है।
नुकसान मेमोरी विखंडन है: Sweep के बाद, मुक्त क्षेत्र व्याप्त क्षेत्रों के साथ वैकल्पिक होते हैं, जिससे बड़े ऑब्जेक्ट्स का आवंटन कठिन हो जाता है। मोबाइल परिदृश्यों में, यह महत्वपूर्ण है क्योंकि हीप आमतौर पर छोटा होता है (Android पर 64–512 MB)।
Copying Collection हीप को दो अर्ध-स्थानों (semi-spaces) में विभाजित करता है। सक्रिय ऑब्जेक्ट्स को एक अर्ध-स्थान से दूसरे में कॉम्पैक्ट रूप में कॉपी किया जाता है, बिना अंतराल के। कॉपी करने के बाद, पुराने अर्ध-स्थान को पूरी तरह से मुक्त घोषित कर दिया जाता है। यह एल्गोरिदम विखंडन को पूरी तरह से समाप्त करता है, लेकिन दोगुनी मेमोरी की आवश्यकता होती है।
मोबाइल वातावरण में, Copying Collection का उपयोग जनरेशनल कलेक्टरों द्वारा युवा ऑब्जेक्ट्स की तेज़ सफाई के लिए किया जाता है, जो सांख्यिकीय रूप से जल्दी मर जाते हैं (कमजोर जनरेशनल परिकल्पना)।
Generational Collection हीप को पीढ़ियों में विभाजित करता है: Young Generation (युवा ऑब्जेक्ट) और Old Generation (पुराने ऑब्जेक्ट जो कई संग्रहों से बच गए)। युवा पीढ़ी का संग्रह (Minor GC) बार-बार और जल्दी किया जाता है, क्योंकि अधिकांश ऑब्जेक्ट युवा मर जाते हैं। पुरानी पीढ़ी का संग्रह (Major GC या Full GC) कम बार होता है लेकिन अधिक समय लेता है।
// जनरेशनल GC का प्रदर्शन: युवा ऑब्जेक्ट जल्दी मरते हैं
void processItems(List<Item> items) {
List<Result> results = new ArrayList<>(); // पूरी विधि तक जीवित रहता है
for (Item item : items) {
Result r = new Result(item.getValue()); // तुरंत मर जाता है
if (r.isValid()) {
process(r); // r कचरा बन जाता है
}
}
saveResults(results); // results Old Gen में चला जाता है
}
इस उदाहरण में, Result ऑब्जेक्ट्स लूप के अंदर बनाए जाते हैं और तुरंत कचरा बन जाते हैं — वे Young GC के लिए आदर्श उम्मीदवार हैं। results ऑब्जेक्ट अधिक समय तक जीवित रहता है और Old Generation में चला जाता है। पीढ़ियों का पृथक्करण Minor GC को पुराने हीप को छुए बिना मिलीसेकंड में युवा ऑब्जेक्ट्स को साफ़ करने की अनुमति देता है।
Android Dalvik VM से ART (Android Runtime) तक विकसित हुआ, और GC कार्यान्वयन उनके बीच मुख्य अंतरों में से एक है। Android में GC आर्किटेक्चर को समझना वास्तविक उपकरणों पर पॉज़ को कम करने वाला कोड लिखने में मदद करता है।
| विशेषता | Dalvik (4.4 तक) | ART (5.0+) |
|---|---|---|
| GC प्रकार | Concurrent Mark के साथ Mark-and-Sweep | Generational + Concurrent |
| विशिष्ट पॉज़ | 10–30 ms | 2–4 ms |
| संहतन (Compaction) | नहीं (केवल विखंडन बढ़ता है) | हाँ (पृष्ठभूमि में, ऐप को रोके बिना) |
| AOT संकलन | JIT (Just-In-Time) | AOT + JIT (हाइब्रिड) |
Dalvik ने एक समवर्ती चरण के साथ Mark-and-Sweep के संयोजन का उपयोग किया। Concurrent Mark ने ऑब्जेक्ट ग्राफ़ ट्रैवर्सल के दौरान एप्लिकेशन को काम जारी रखने की अनुमति दी, लेकिन Sweep चरण के लिए सभी थ्रेड्स को रोकना आवश्यक था (Stop-The-World)। कम RAM (512 MB — 1 GB) वाले उपकरणों पर, पॉज़ 30 ms तक पहुँच गए, जिससे इंटरफ़ेस में ध्यान देने योग्य हिचकी आई। इसके अलावा, Dalvik ने हीप को संहत (compact) नहीं किया, इसलिए लंबे संचालन के बाद विखंडन बढ़ गया, और बड़े ऑब्जेक्ट्स (जैसे Bitmap) का आवंटन पर्याप्त कुल मुक्त मेमोरी होने पर भी OutOfMemoryError फेंक सकता था।
ART (Android Runtime) ने समवर्ती संहतन के साथ एक जनरेशनल कलेक्टर पेश किया। हीप तीन क्षेत्रों में विभाजित है: Young, Mature (Old Generation का एनालॉग), और Large Object Space (12 KB से बड़े ऑब्जेक्ट्स के लिए)। अधिकांश मामलों में Young Region का संग्रह थ्रेड्स को रोके बिना समानांतर में होता है। Android 10+ में, Concurrent Copying पेश की गई — संहतन Stop-The-World के बिना पृष्ठभूमि थ्रेड में चलता है।
ART की आर्किटेक्चर के कारण, विशिष्ट GC पॉज़ 2–4 ms तक कम हो गए, और युवा ऑब्जेक्ट्स की प्रधानता वाले परिदृश्यों में — 0.5–1 ms तक। इसने Android उपकरणों को सक्रिय मेमोरी संचालन के दौरान भी स्थिर 60 FPS बनाए रखने की अनुमति दी।
Java इकोसिस्टम में, GC के कई कार्यान्वयन हैं, प्रत्येक का अपना प्रदर्शन प्रोफ़ाइल है। Android डेवलपमेंट के लिए, विकल्प ART तक सीमित है, लेकिन Java GC का ज्ञान मोबाइल एप्लिकेशन के लिए सर्वर-साइड कोड लिखने और Kotlin Multiplatform के साथ डेवलपमेंट करते समय उपयोगी है।
Serial GC पूर्ण एप्लिकेशन स्टॉप (Stop-The-World) के साथ एक एकल-थ्रेडेड कलेक्टर है। प्रत्येक Mark, Sweep और Compact ऑपरेशन एक थ्रेड द्वारा किया जाता है। प्रदर्शन कम है — मोबाइल सर्वर के लिए उपयोग नहीं किया जाता है। केवल 100 MB तक के हीप वाले छोटे एप्लिकेशन के लिए उपयुक्त है।
Parallel GC (जिसे Throughput Collector के रूप में भी जाना जाता है) सभी संग्रह चरणों के लिए कई थ्रेड्स का उपयोग करता है। यह अधिकतम थ्रूपुट (throughput) की ओर उन्मुख है — एप्लिकेशन रनटाइम के सापेक्ष GC पर खर्च होने वाले समय को कम करना। JVM में -XX:+UseParallelGC फ़्लैग के माध्यम से सक्षम किया जाता है।
G1 (Garbage-First) GC Java 9+ में डिफ़ॉल्ट कलेक्टर है। हीप 1–32 MB के क्षेत्रों में विभाजित है। G1 पॉज़ समय की भविष्यवाणी करता है और निर्दिष्ट सीमा (डिफ़ॉल्ट 200 ms) के भीतर रहने का प्रयास करता है। प्राथमिकता: सबसे अधिक कचरे वाले क्षेत्र पहले साफ़ किए जाते हैं (इसलिए नाम)। G1 बड़े हीप वाले सर्वर (4–64 GB) के लिए पूर्वानुमानित पॉज़ के साथ प्रभावी है।
// 100 ms लक्ष्य पॉज़ के साथ G1 GC सक्षम करना
// java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -jar app.jar
public class MemoryMonitor {
private static final long THRESHOLD = 512 * 1024 * 1024; // 512 MB
public void checkHeapUsage() {
Runtime rt = Runtime.getRuntime();
long used = rt.totalMemory() - rt.freeMemory();
if (used > THRESHOLD) {
System.out.println("Heap usage exceeded threshold: " + used);
System.out.println("Consider reducing allocations");
}
}
}
Runtime के माध्यम से हीप की निगरानी प्रारंभिक चरण में मेमोरी लीक का पता लगाने की अनुमति देती है। यदि स्थिर संचालन में used अधिकतम हीप के 80% से अधिक हो जाता है — यह संभावित लीक या एप्लिकेशन द्वारा अत्यधिक मेमोरी खपत का संकेत है।
आधुनिक ART GC भी सभी समस्याओं का समाधान नहीं करता — अनुचित मेमोरी उपयोग jank और ANR (Application Not Responding) का मुख्य कारण बना हुआ है। आइए मुख्य परिदृश्यों और ऑप्टिमाइज़ेशन विधियों को देखें।
GC Pauses — संग्रह के दौरान एप्लिकेशन थ्रेड्स का रुकना। स्क्रीन पर, यह छूटे हुए फ्रेम के रूप में प्रकट होता है, जब दो फ्रेम के बीच का समय 16.6 ms (60 FPS) से अधिक हो जाता है। यदि GC 30 ms तक चलता है, तो दो के बजाय केवल एक फ्रेम खींचा जाता है — उपयोगकर्ता इंटरफ़ेस में हिचकी देखता है।
लंबे पॉज़ के मुख्य कारण: Old Generation में बड़ी संख्या में जीवित ऑब्जेक्ट, हीप विखंडन, बार-बार Full GC। निदान के लिए Android Studio Profiler और systrace का उपयोग किया जाता है।
GC-अनुकूल कोड का मुख्य नियम आवंटित ऑब्जेक्ट्स की संख्या को कम करना है। प्रत्येक नए ऑब्जेक्ट को न केवल मेमोरी आवंटन की आवश्यकता होती है बल्कि बाद में संग्रह की भी। भले ही GC तेज़ हो, प्रति सेकंड 1000 अतिरिक्त आवंटन कलेक्टर के लिए 1000 जाँचें उत्पन्न करते हैं।
मेमोरी लीक तब होता है जब कोई ऑब्जेक्ट सुलभ बना रहता है भले ही उसकी अब आवश्यकता न हो। GC ऐसे ऑब्जेक्ट को हटा नहीं सकता, और मेमोरी धीरे-धीरे समाप्त हो जाती है। सामान्य कारण: अपंजीकृत श्रोता, Activity के स्थिर संदर्भ, बाहरी संदर्भ को कैप्चर करने वाली अनाम कक्षाएँ, और बंद न किए गए Cursor/InputStream।
// मेमोरी लीक: अनाम वर्ग Activity का संदर्भ रखता है
public void startTask() {
new Thread(new Runnable() { // अंतर्निहित रूप से this (Activity) रखता है
@Override
public void run() {
// लंबा ऑपरेशन...
System.out.println("Done");
}
}).start();
}
// सुधार: स्थैतिक नेस्टेड वर्ग + WeakReference
private static class TaskRunnable implements Runnable {
private WeakReference<Activity> activityRef;
TaskRunnable(Activity activity) {
this.activityRef = new WeakReference<>(activity);
}
@Override
public void run() {
Activity act = activityRef.get();
if (act != null) {
// Activity के साथ सुरक्षित कार्य
}
}
}
इस उदाहरण में, अनाम Runnable Activity के लिए एक अंतर्निहित संदर्भ कैप्चर करता है। जब तक थ्रेड जीवित है — GC द्वारा Activity को एकत्र नहीं किया जा सकता, भले ही उपयोगकर्ता ने स्क्रीन बंद कर दी हो। WeakReference + स्थैतिक वर्ग सुधार इस श्रृंखला को तोड़ता है और Activity को मुक्त करने की अनुमति देता है।
अक्सर पूछे जाने वाले प्रश्न
Android (ART) में GC समवर्ती संहतन वाला एक जनरलनल कलेक्टर है, जो सीमित मेमोरी वाले मोबाइल उपकरणों के लिए अनुकूलित है। Java GC (G1, ZGC) बड़े हीप और पूर्वानुमानित पॉज़ वाले सर्वर-साइड कलेक्टर हैं। ART GC JVM फ़्लैग का उपयोग नहीं करता — सभी ट्यूनिंग OS स्तर पर स्वचालित रूप से की जाती है।
Stop-The-World वह क्षण है जब कलेक्टर ऑब्जेक्ट ग्राफ़ को सुरक्षित रूप से ट्रैवर्स करने या मेमोरी मुक्त करने के लिए एप्लिकेशन के सभी थ्रेड्स को रोकता है। STW जितना लंबा होगा, jank उतना ही अधिक ध्यान देने योग्य होगा। ART ने अपनी जनरलनल आर्किटेक्चर के कारण विशिष्ट STW समय को 2–4 ms तक कम कर दिया।
Android Studio Memory Profiler का उपयोग करें — यह हीप वृद्धि, आवंटन संख्या दिखाता है और Heap Dump लेने की अनुमति देता है। गहन विश्लेषण के लिए, LeakCanary का उपयोग करें — लाइब्रेरी स्वचालित रूप से लीक का पता लगाती है और GC संग्रह को रोकने वाली संदर्भ श्रृंखला दिखाती है।
Full GC Old Generation सहित सभी हीप पीढ़ियों का पूर्ण संग्रह है। मोबाइल एप्लिकेशन में, Full GC 50–200 ms तक चल सकता है, जिससे ध्यान देने योग्य jank या ANR हो सकता है। मुख्य कारण: हीप विखंडन, मेमोरी लीक, Old Generation सीमा पार करना।
Kotlin संरचित समवर्तीता के साथ कोरूटीन प्रदान करता है — स्कोप रद्दीकरण स्वचालित रूप से सभी चाइल्ड कोरूटीन को रद्द करता है, लीक को रोकता है। Kotlin में विलंबित आरंभीकरण के लिए lazy डेलीगेट और स्कोप फ़ंक्शन भी हैं जो अस्थायी ऑब्जेक्ट्स की संख्या कम करते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें