Xotirani yeydi va shishadi — bu nima, sabablari va qanday qochish

Muallif: IT Sectr Nashr etilgan: 2026-07-28 O'qish vaqti: 10 daq

Xotira oqishi — mobil ishlanmadagi eng makkor muammolardan biridir. Ilova xotiri doimiy ravishda o'sib boradi, toki operatsion tizim tomonidan belgilangan chegaraga yetguncha, shundan so'ng OutOfMemoryError yoki majburiy tugatish yuz beradi. Square Engineering ma'lumotlariga ko'ra, taxminan 40% Android ilovalarida faqat profillash vaqtida aniqlanishi mumkin bo'lgan kamida bitta xotira oqishi mavjud. Xotira o'sishining sabablari va oldini olish usullarini ko'rib chiqamiz.

Asosiy fikrlar

  • GC reachability — agar ob'ektga ildiz to'plamidan faol havola mavjud bo'lsa, u o'chirilmaydi
  • Statik havolalar Activity yoki Context-ga — Android-da eng ko'p tarqalgan oqish sababi
  • LeakCanary — Android-da avtomatik oqish aniqlash uchun standart vosita
  • WeakReference — axlat yig'ilishiga to'sqinlik qilmasligi kerak bo'lgan havolalar uchun yechim
  • Lifecycle-aware komponentlari ko'rinish yo'q qilinganda obunalarni avtomatik bekor qiladi

Xotira oqishi va ilova shishishi nima?

Xotira oqishi (memory leak) — ilovaga endi kerak bo'lmagan ob'ektning, ildiz to'plamidan (GC Root) faol havola mavjudligi sababli xotirada qolishda davom etishi. Axlat yig'uvchi bunday ob'ektni tirik deb hisoblaydi va uni o'chirmaydi.

Xotira shishishi (memory bloat) — ilova joriy vazifalarni bajarish uchun zarur bo'lganidan ko'ra ko'proq xotira iste'mol qiladigan kengroq muammo. Sabablari: haddan tashqari keshlash, ob'ektlarning takrorlanishi, optimal bo'lmagan ma'lumot tuzilmalari va xotira parchalanishi.

Android ilovalari uchun cheklangan xotira ajratiladi (odatda qurilma va OT versiyasiga qarab 64-512 MB). iOS chegarasi kamroq qattiq, ammo tizim chegaraga yaqinlashganda xotira ogohlantirishini yuboradi.

XususiyatAndroidiOS
Xotira chegarasi64-512 MB (qurilmaga bog'liq)Yashirin (tizim)
Axlat yig'ilishiART (Concurrent, Compact)ARC (Automatic Reference Counting)
Oqish mexanizmiGC Root havolalariRetain cycles (kuchli havola sikllari)
NatijaOutOfMemoryErrorXotira ogohlantirishi → tugatish

Facebook Engineering Blog ma'lumotlariga ko'ra, xotira oqishlari mobil ilovalardagi crash hisobotlarining ~15% sababidir. Android-da bunga xotira yetishmasligida tez-tez GC pauzalari sababli ANR qo'shiladi.

Android va iOS-da tipik xotira oqishi naqshlari

Activity-ga statik havola — Android oqishlarining klassikasi. Statik maydon yoki singleton Activity-ga havola saqlasa, singleton tirik ekan, finish() dan keyin ham GC tomonidan yig'ilmaydi. Activity View hierarchy, resurslar va Context-ni o'z ichiga olgan og'ir ob'ektdir.

kotlin
object LeakHolder {
    var activityRef: Activity ?= null // oqish: Activity ga statik havola
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle ?= null) {
        super.onCreate(savedInstanceState)
        LeakHolder.activityRef = this // ❌ MainActivity hech qachon GC tomonidan yig'ilmaydi
    }
}

Anonim sinflar va lambdalar — yashirincha tashqi sinfga havola saqlaydi. Agar Runnable yoki Callback tashqi xizmatga uzatilsa va Activity yo'q qilinsa, anonim sinf ob'ekti hali ham navbatda qoladi va Activity ning axlat yig'ilishiga ketishiga to'sqinlik qiladi.

  • Handler kechikish bilan — Activity yo'q qilingan bo'lsa, lekin Handler.postDelayed hali bajarilmagan bo'lsa, Activity oqadi
  • Thread va AsyncTask — ekran aylantirilganda Activity qayta yaratiladi, eski Thread esa eski Activity-ga havolani saqlaydi
  • Retrofit/Callback — anonim Callback presenter yoki fragment ga havola saqlaydi
  • Kuzatuvchilar (Observers) — onDestroy da bekor qilinmagan LiveData yoki RxJava obunalari

iOS-da asosiy muammo retain cycles: ikkita ob'ekt bir-biriga kuchli havolalar saqlaydi va ARC hech biri uchun havola sonini nolga tushirolmaydi. Oddiy hol: self ni kuchli tutadigan closure va self ning closure ga havola saqlashi.

Xotira oqishlarini qanday aniqlash mumkin?

LeakCanary — Android-da avtomatik oqish aniqlash uchun Square kutubxonasi. Activity yoki Fragment yo'q qilingandan so'ng ob'ektning GC tomonidan yig'ilgan-yig'ilmaganligini tekshiradi. Agar yo'q bo'lsa — heap dump qiladi va oqish trace-ni ko'rsatadi.

kotlin
// LeakCanary 2.x — Application orqali avto-integratsiya
class ExampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // LeakCanary debug qurilmasida avtomatik o'rnatiladi
        // ContentProvider orqali — nol kod sozlamasi
    }
}

// Majburiy tekshirish chaqiruvi
AppWatcher.objectWatcher.watch(watchedObject, "leak description")

Android Studio Profiler — real vaqtda xotirani kuzatish uchun o'rnatilgan vosita. Heap dump yozishga, shubhali ob'ektlarni (Retained Size > 1 MB) topishga va har bir ob'ektgacha GC root yo'lini kuzatishga imkon beradi.

iOS uchun Xcode Memory Graph Debugger dan foydalaning. U xotiradagi ob'ektlar grafigini vizuallashtiradi, retain cycles ni ko'rsatadi va aylanma havolalarni darhol aniqlashga imkon beradi. Uzoq muddatli kuzatish uchun Instruments > Allocations ham mavjud.

Oqishlarning oldini olish strategiyalari

WeakReference — axlat yig'ilishiga to'sqinlik qilmasligi kerak bo'lgan havolalar uchun asosiy mexanizm. GC ob'ektni o'chirishga qaror qilsa, WeakReference null qaytaradi. Qayta chaqiruvlar, tinglovchilar va fon iplaridan UI komponentlariga havolalar uchun ishlatiladi.

Lifecycle-aware komponentlari — Android Jetpack (Lifecycle, LiveData, Flow, coroutines) da amalga oshirilgan arxitektura yondashuvi. Obunalar onDestroy da avtomatik bekor qilinadi, bu esa asosiy oqish sinfini yo'q qiladi.

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)
            // korutina onCleared() da avtomatik bekor qilinadi
        }
    }
}

viewModelScope va lifecycleScope — Android-da hayot aylanish hodisasi paytida bekor qilinadigan o'rnatilgan CoroutineScope-lar. Bu korutinlar orqali oqishlarni yo'q qiladi — zamonaviy Android ishlanmasidagi eng keng tarqalgan stsenariy.

  • Ishlatmang Context, Activity, View yoki Fragment-ga statik havolalar
  • Bekor qiling barcha RxJava obunalarini disposeBag / CompositeDisposable bilan onDestroy da
  • Ishlating [weak self] / [unowned self] iOS closure-larida retain cycles oldini olish uchun
  • Tekshiring Bitmap va katta ob'ektlarni — ular qayta ishlanishi yoki nollanishi kerak

Xotira profillash vositalari

Memory Profiler in Android Studio — xotirani kuzatish uchun asosiy vosita. Jonli ajratmalarni, xotira suratlarini, turlar bo'yicha ob'ektlar sonini ko'rsatadi. Dump yozishga va shubhali ob'ektlarni topish uchun MAT (Memory Analyzer Tool) da tahlil qilishga imkon beradi.

Eclipse MAT — xotira dump-lari uchun ish stoli analizatori. Android Studio dan HPROF fayli yuklangandan so'ng MAT dominator daraxtini quradi, har bir ob'ektning retain hajmini ko'rsatadi va Leak Suspects Report orqali shubhali oqishlarning avtomatik tahlilini taklif qiladi.

Xcode Memory Graph — retain cycles uchun vizual debugger. Memory Graph Debugger tugmasini bosganda Xcode ilovani to'xtatadi, xotiradagi ob'ektlarning to'liq grafigini quradi va retain cycles ni qizil rang bilan ajratib ko'rsatadi.

VositaPlatformaXususiyat
LeakCanaryAndroidYo'q qilishdan keyin avtomatik oqish aniqlash
Memory ProfilerAndroid StudioHeap dump + jonli ajratmalar
Eclipse MATAndroidDominator daraxti, Leak Suspects Report
Memory GraphiOS (Xcode)Retain cycles vizuallashtiruvchisi

Google I/O 2023 ma'lumotlariga ko'ra, debug qurilmalarida LeakCanary ishlatadigan ilovalar joriy qilingandan keyin dastlabki 2 oy ichida xotira bilan bog'liq crash-lar sonini 30-50% kamaytiradi. LeakCanary ni loyihaga onboarding bosqichida qo'shish tavsiya etiladi.

Tez-tez beriladigan savollar

Xotira oqishi shishishdan qanday farq qiladi?

Oqish — kod uchun mavjud bo'lmagan, lekin faol havolalar sababli GC tomonidan o'chirilmaydigan ob'ektlar. Shishish — ilova mantiqan kerak bo'lgan, lekin haddan tashqari miqdordagi ob'ektlarni xotirada saqlashi (masalan, 80 MB ishlaydigan ilovada 50 MB keshlash). Shishish arxitektura yo'li bilan davolanadi, oqish — havolalarni to'g'ri boshqarish orqali.

LeakCanary oqishlarni qanday topadi?

LeakCanary ObjectWatcher ishlatadi — onDestroy() Activity dan keyin Activity ga WeakReference yaratadi va GC ni ishga tushiradi. Agar 5 soniyadan keyin WeakReference tozalanmasa, LeakCanary heap dump qiladi, GC Root dan ob'ektgacha eng qisqa havola zanjirini tahlil qiladi va fayl nomi va kod qatori bilan aniq oqish stekini ko'rsatadi.

Nima uchun Bitmap tez-tez OutOfMemoryError keltirib chiqaradi?

Bitmap Java xotirasidan tashqarida, native xotirada (native heap) joy egallaydi. Bitta Bitmap ning hajmi = en × balandlik × 4 bayt (ARGB_8888). 12 MP foto (4000×3000) 48 MB egallaydi. Android har doim ham native xotirani o'z vaqtida bo'shata olmaydi, bu esa bir nechta Bitmap to'planganda yetarli Java xotirasi bo'lsa ham OOM ga olib keladi.

iOS da retain cycle nima?

Retain cycle — ARC da ikkita ob'ekt bir-biriga kuchli havolalar saqlaganda va havola soni hech qachon nolga yetmaganda yuz beradi. Oddiy misol: ViewController ning closure ga kuchli havolasi va closure ning self ni kuchli tutishi. Yechim: closure-larda [weak self] yoki [unowned self] ishlating.

Android da maksimal xotira hajmi qancha?

Xotira hajmi qurilma va Android versiyasiga bog'liq. Eski qurilmalar uchun (API 15-24) — 64-128 MB. Zamonaviy qurilmalar uchun (API 25+) — 256-512 MB. Aniq qiymatni ActivityManager.getMemoryClass() orqali olish mumkin. Katta ilovalar (o'yinlar, muharrirlar) uchun manifestda largeHeap=true mavjud, 1 GB gacha beradi.

Xulosa

  • Xotira oqishi — ildiz to'plamidan faol havola sababli GC tomonidan o'chirilmaydigan ob'ekt; shishish — aniq oqishlarsiz haddan tashqari xotira iste'moli
  • Statik havolalar Activity, Context, View-ga — Android-da oqishlarning birinchi raqamli sababi; yechim — WeakReference yoki Application Context
  • Anonim sinflar va lambdalar yashirincha tashqi sinfga havola saqlaydi; bekor qilinmagan callbacklar — ikkinchi eng keng tarqalgan sabab
  • LeakCanary — Android-da avtomatik oqish aniqlash standarti; integratsiya 5 daqiqa davom etadi va crash darajasini 30-50% kamaytiradi
  • lifecycleScope va viewModelScope korutinlarni destroy da avtomatik bekor qiladi, butun bir oqish sinfini yo'q qiladi
  • Retain cycles iOS da closure va delegate larda weak/unowned self bilan hal qilinadi
  • Xotirani profillang har sprintda kamida bir marta — MAT yoki Memory Graph bilan heap dump code review ning bir qismi bo'lishi kerak

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing