मेमोरी लीक और ब्लोट — यह क्या है, कारण और कैसे बचें

लेखक: IT Sectr प्रकाशित: 2026-07-28 पढ़ने का समय: 10 मिनट

मेमोरी लीक — मोबाइल डेवलपमेंट में सबसे कपटी समस्याओं में से एक। ऐप की मेमोरी उपयोग लगातार बढ़ता रहता है जब तक कि यह OS द्वारा निर्धारित सीमा तक नहीं पहुँच जाता, जिसके बाद OutOfMemoryError या जबरन समाप्ति होती है। Square Engineering के अनुसार, लगभग 40% Android ऐप्स में कम से कम एक मेमोरी लीक होती है जो केवल प्रोफाइलिंग के माध्यम से पता लगाई जा सकती है। आइए कारणों और मेमोरी वृद्धि को रोकने के तरीकों की जाँच करें।

मुख्य बातें

  • GC पहुँच — यदि रूट सेट से कोई सक्रिय संदर्भ है तो ऑब्जेक्ट हटाया नहीं जाता
  • Activity या Context के स्थिर संदर्भ — Android में लीक का सबसे सामान्य कारण
  • LeakCanary — Android में स्वचालित लीक पहचान के लिए मानक उपकरण
  • WeakReference — उन संदर्भों का समाधान जो गार्बेज कलेक्शन में बाधा नहीं डालने चाहिए
  • Lifecycle-aware घटक व्यू नष्ट होने पर स्वचालित रूप से सब्सक्रिप्शन रद्द करते हैं

मेमोरी लीक और ऐप ब्लोट क्या है?

मेमोरी लीक — एक स्थिति जहाँ एक ऑब्जेक्ट जो अब ऐप के लिए आवश्यक नहीं है, हीप में बना रहता है क्योंकि GC रूट सेट से एक सक्रिय संदर्भ अभी भी उसकी ओर इशारा करता है। गार्बेज कलेक्टर ऐसे ऑब्जेक्ट को जीवित मानता है और उसे हटाता नहीं है।

मेमोरी ब्लोट — एक व्यापक समस्या जहाँ ऐप अपने वर्तमान कार्यों को करने के लिए आवश्यकता से अधिक मेमोरी का उपभोग करता है। कारण: अत्यधिक कैशिंग, ऑब्जेक्ट डुप्लिकेशन, उप-इष्टतम डेटा संरचनाएँ, और हीप विखंडन।

Android में, प्रत्येक ऐप के लिए एक सीमित हीप आवंटित किया जाता है (आमतौर पर डिवाइस और OS संस्करण के आधार पर 64–512 MB)। iOS में, सीमा कम सख्त है, लेकिन सीमा के पास पहुँचने पर सिस्टम एक मेमोरी चेतावनी भेजता है।

विशेषताAndroidiOS
हीप सीमा64–512 MB (डिवाइस पर निर्भर)अंतर्निहित (सिस्टम)
गार्बेज कलेक्शनART (समवर्ती, कॉम्पैक्ट)ARC (स्वचालित संदर्भ गणना)
लीक तंत्रGC रूट संदर्भरिटेन चक्र (मजबूत संदर्भ चक्र)
परिणामOutOfMemoryErrorमेमोरी चेतावनी → समाप्ति

Facebook Engineering Blog के अनुसार, मेमोरी लीक मोबाइल ऐप्स में लगभग ~15% क्रैश रिपोर्ट का कारण बनती हैं। Android में, मेमोरी कम होने पर बार-बार GC रुकने के कारण ANR भी जुड़ जाते हैं।

Android और iOS में सामान्य मेमोरी लीक पैटर्न

Activity का स्थिर संदर्भ — एक क्लासिक Android लीक। यदि कोई स्थिर फ़ील्ड या सिंगलटन Activity का संदर्भ रखता है, तो finish() के बाद भी GC द्वारा इसे एकत्र नहीं किया जाएगा जब तक सिंगलटन जीवित है। Activity एक भारी ऑब्जेक्ट है जिसमें व्यू पदानुक्रम, संसाधन और Context शामिल हैं।

kotlin
object LeakHolder {
    var activityRef: Activity ?= null // leak: static reference to Activity
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle ?= null) {
        super.onCreate(savedInstanceState)
        LeakHolder.activityRef = this // ❌ MainActivity will never be GC'd
    }
}

अनाम वर्ग और लैम्ब्डा — बाहरी वर्ग का एक संदर्भ अंतर्निहित रूप से रखते हैं। यदि Runnable या Callback किसी बाहरी सेवा में भेजा जाता है और Activity नष्ट हो जाती है, तो अनाम वर्ग का ऑब्जेक्ट अभी भी कतार में रहता है और Activity को गार्बेज कलेक्ट होने से रोकता है।

  • Handler विलंब के साथ — यदि Activity नष्ट हो जाती है लेकिन Handler.postDelayed अभी तक निष्पादित नहीं हुआ है, तो Activity लीक हो जाती है
  • Thread और AsyncTask — स्क्रीन घुमाने पर, Activity फिर से बनाई जाती है जबकि पुराना Thread पुरानी Activity का संदर्भ रखता रहता है
  • Retrofit/Callback — एक अनाम Callback प्रेजेंटर या फ़्रैगमेंट का संदर्भ रखता है
  • पर्यवेक्षक — onDestroy पर बिना अनसब्सक्राइब किए LiveData या RxJava सब्सक्रिप्शन

iOS में, मुख्य समस्या रिटेन चक्र है: दो ऑब्जेक्ट एक-दूसरे के मजबूत संदर्भ रखते हैं, और ARC किसी के लिए भी संदर्भ गणना को शून्य नहीं कर सकता। एक विशिष्ट मामला: एक क्लोज़र जो self को मजबूती से कैप्चर करता है, और self जो क्लोज़र का संदर्भ रखता है।

मेमोरी लीक का पता कैसे लगाएं?

LeakCanary — Android में स्वचालित लीक पहचान के लिए Square की एक लाइब्रेरी। Activity या Fragment नष्ट होने के बाद, यह जाँचता है कि ऑब्जेक्ट GC द्वारा एकत्र किया गया था या नहीं। यदि नहीं, तो यह हीप डंप लेता है और लीक ट्रेस दिखाता है।

kotlin
// LeakCanary 2.x — auto-integration via Application
class ExampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // LeakCanary auto-installs in debug build
        // via ContentProvider — zero code setup
    }
}

// Force check invocation
AppWatcher.objectWatcher.watch(watchedObject, "leak description")

Android Studio Profiler — रीयल-टाइम मेमोरी मॉनिटरिंग के लिए एक अंतर्निहित उपकरण। यह हीप डंप रिकॉर्ड करने, संदिग्ध ऑब्जेक्ट (Retained Size > 1 MB) खोजने और प्रत्येक ऑब्जेक्ट तक GC रूट पथ का पता लगाने की अनुमति देता है।

iOS के लिए, Xcode Memory Graph Debugger का उपयोग करें। यह मेमोरी में ऑब्जेक्ट ग्राफ़ को विज़ुअलाइज़ करता है, रिटेन चक्र दिखाता है और तुरंत गोलाकार संदर्भों का पता लगाने की अनुमति देता है। दीर्घकालिक निगरानी के लिए Instruments > Allocations भी उपलब्ध है।

रोकथाम की रणनीतियाँ

WeakReference — उन संदर्भों के लिए एक बुनियादी तंत्र जो गार्बेज कलेक्शन में हस्तक्षेप नहीं करना चाहिए। यदि GC किसी ऑब्जेक्ट को एकत्र करने का निर्णय लेता है, तो WeakReference null लौटाता है। इसका उपयोग कॉलबैक, श्रोताओं और पृष्ठभूमि थ्रेड से UI घटकों के संदर्भों के लिए किया जाता है।

Lifecycle-aware घटक — Android Jetpack (Lifecycle, LiveData, Flow, coroutines) में लागू एक आर्किटेक्चरल दृष्टिकोण। सब्सक्रिप्शन onDestroy पर स्वचालित रूप से रद्द हो जाते हैं, जो लीक के मुख्य वर्ग को समाप्त करता है।

kotlin
class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<List<User>>()
    val data: LiveData<List<User>> get() = _data

    fun loadData() {
        viewModelScope.launch {
            val result = repository.fetchData()
            _data.postValue(result)
            // coroutine auto-cancels on onCleared()
        }
    }
}

viewModelScope और lifecycleScope — Android में अंतर्निहित CoroutineScope जो संबंधित जीवनचक्र घटना पर रद्द हो जाते हैं। यह कोरूटीन के माध्यम से लीक को समाप्त करता है — आधुनिक Android विकास में सबसे आम परिदृश्य।

  • उपयोग न करें Context, Activity, View या Fragment के स्थिर संदर्भ
  • रद्द करें onDestroy पर disposeBag / CompositeDisposable में सभी RxJava सब्सक्रिप्शन
  • उपयोग करें iOS क्लोज़र में [weak self] / [unowned self] रिटेन चक्र को रोकने के लिए
  • जाँचें Bitmap और बड़े ऑब्जेक्ट — उन्हें रिसाइकिल या शून्य किया जाना चाहिए

मेमोरी प्रोफाइलिंग उपकरण

Android Studio में Memory Profiler — हीप मॉनिटरिंग के लिए प्राथमिक उपकरण। यह लाइव आवंटन, हीप स्नैपशॉट और प्रकार के अनुसार ऑब्जेक्ट गणना दिखाता है। यह एक डंप रिकॉर्ड करने और संदिग्ध ऑब्जेक्ट खोजने के लिए MAT (Memory Analyzer Tool) में विश्लेषण करने की अनुमति देता है।

Eclipse MAT — एक डेस्कटॉप हीप डंप विश्लेषक। Android Studio से HPROF फ़ाइल लोड करने के बाद, MAT एक डोमिनेटर ट्री बनाता है, प्रत्येक ऑब्जेक्ट का रिटेन आकार दिखाता है, और Leak Suspects Report के माध्यम से स्वचालित लीक संदिग्ध विश्लेषण प्रदान करता है।

Xcode Memory Graph — एक विज़ुअल रिटेन चक्र डिबगर। Memory Graph Debugger बटन पर क्लिक करने पर, Xcode ऐप को रोकता है, मेमोरी में एक पूरा ऑब्जेक्ट ग्राफ़ बनाता है, और रिटेन चक्र को लाल रंग में हाइलाइट करता है।

उपकरणप्लेटफ़ॉर्मविशेषता
LeakCanaryAndroidडिस्ट्रॉय के बाद लीक का स्वतः पता लगाना
Memory ProfilerAndroid Studioहीप डंप + लाइव आवंटन
Eclipse MATAndroidडोमिनेटर ट्री, Leak Suspects Report
Memory GraphiOS (Xcode)रिटेन चक्र विज़ुअलाइज़र

Google I/O 2023 के अनुसार, डीबग बिल्ड में LeakCanary का उपयोग करने वाले ऐप्स मेमोरी-संबंधित क्रैश को अपनाने के पहले 2 महीनों में 30–50% कम करते हैं। प्रोजेक्ट ऑनबोर्डिंग चरण के दौरान LeakCanary जोड़ने की सिफारिश की जाती है।

अक्सर पूछे जाने वाले प्रश्न

मेमोरी लीक ब्लोट से कैसे अलग है?

लीक — ऑब्जेक्ट जो कोड के लिए पहुँच योग्य नहीं हैं लेकिन सक्रिय संदर्भों के कारण GC द्वारा एकत्र नहीं किए जाते। ब्लोट — ऐप उन ऑब्जेक्ट को रखता है जो तार्किक रूप से आवश्यक हैं लेकिन अत्यधिक मात्रा में (उदाहरण: 80 MB के चल रहे ऐप में 50 MB कैश)। ब्लोट वास्तुशिल्प रूप से ठीक किया जाता है; लीक — सही संदर्भ प्रबंधन के माध्यम से।

LeakCanary लीक कैसे ढूँढता है?

LeakCanary ObjectWatcher का उपयोग करता है — Activity के onDestroy() के बाद, यह Activity पर एक WeakReference बनाता है और GC चलाता है। यदि 5 सेकंड के बाद WeakReference साफ़ नहीं होता है, तो LeakCanary हीप डंप लेता है, GC Root से ऑब्जेक्ट तक सबसे छोटी संदर्भ श्रृंखला का विश्लेषण करता है, और फ़ाइल और कोड लाइन के साथ सटीक लीक स्टैक दिखाता है।

Bitmap अक्सर OutOfMemoryError क्यों करता है?

Bitmap जावा हीप के बाहर मूल मेमोरी (नेटिव हीप) में मेमोरी घेरता है। एक Bitmap का आकार = चौड़ाई × ऊँचाई × 4 बाइट (ARGB_8888)। 12 MP फ़ोटो (4000×3000) 48 MB लेती है। Android हमेशा समय पर मूल मेमोरी मुक्त नहीं कर सकता, इसलिए कई Bitmaps के संचय से पर्याप्त Java हीप होने पर भी OOM होता है।

iOS में रिटेन चक्र क्या है?

रिटेन चक्र — ARC में एक स्थिति जहाँ दो ऑब्जेक्ट एक-दूसरे के मजबूत संदर्भ रखते हैं, और संदर्भ गणना कभी शून्य तक नहीं पहुँचती। एक विशिष्ट उदाहरण: एक ViewController जिसका क्लोज़र पर मजबूत संदर्भ है, और क्लोज़र self को मजबूती से कैप्चर करता है। समाधान: क्लोज़र में [weak self] या [unowned self] का उपयोग करें।

Android पर अधिकतम हीप आकार क्या है?

हीप का आकार डिवाइस और Android संस्करण पर निर्भर करता है। पुराने उपकरणों (API 15–24) के लिए — 64–128 MB। आधुनिक (API 25+) के लिए — 256–512 MB। सटीक मान ActivityManager.getMemoryClass() के माध्यम से प्राप्त किया जा सकता है। बड़े ऐप्स (गेम, संपादक) के लिए, मेनिफ़ेस्ट में largeHeap=true 1 GB तक प्रदान करता है।

सारांश

  • मेमोरी लीक — एक ऑब्जेक्ट जो रूट सेट से सक्रिय संदर्भ के कारण GC द्वारा एकत्र नहीं किया गया; ब्लोट — स्पष्ट लीक के बिना अत्यधिक मेमोरी खपत
  • Activity, Context या View के स्थिर संदर्भ — Android में लीक का नंबर एक कारण; समाधान — WeakReference या Application Context
  • अनाम वर्ग और लैम्ब्डा बाहरी वर्ग का अंतर्निहित संदर्भ रखते हैं; रद्द न किए गए कॉलबैक दूसरा सबसे सामान्य कारण हैं
  • LeakCanary — Android में लीक की स्वतः पहचान के लिए मानक; एकीकरण में 5 मिनट लगते हैं और क्रैश दर 30–50% कम करता है
  • lifecycleScope और viewModelScope नष्ट होने पर कोरूटीन को स्वचालित रूप से रद्द करते हैं, लीक की एक पूरी श्रेणी को समाप्त करते हैं
  • iOS में रिटेन चक्र क्लोज़र और डेलिगेट्स में weak/unowned self से हल होते हैं
  • मेमोरी प्रोफाइल करें प्रति स्प्रिंट कम से कम एक बार — MAT या Memory Graph के साथ हीप डंप को कोड रिव्यू का हिस्सा बनना चाहिए

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें