Yaddaşı yeyir və şişir — bu nədir, səbəbləri və necə qarşısını almaq olar

Müəllif: IT Sectr Dərc olunub: 2026-07-28 Oxuma vaxtı: 10 dəq

Yaddaş sızması — mobil inkişafda ən gizli problemlərdən biridir. Tətbiqin yaddaşı durmadan artır, nəhayət ƏS tərəfindən təyin edilmiş həddə çatana qədər, bundan sonra OutOfMemoryError və ya məcburi dayandırma baş verir. Square Engineering məlumatlarına görə, təxminən 40% Android tətbiqlərində yalnız profilləmə zamanı aşkar edilə bilən ən azı bir yaddaş sızması var. Yaddaş artımının səbəblərini və qarşısının alınması üsullarını nəzərdən keçirək.

Əsas məqamlar

  • GC reachability — obyektə kök dəstindən aktiv istinad varsa, o silinmir
  • Statik istinadlar Activity və ya Context-ə — Android-də ən çox yayılmış sızma səbəbi
  • LeakCanary — Android-də avtomatik sızma aşkarlanması üçün standart alət
  • WeakReference — zibil toplanmasına mane olmamalı olan istinadlar üçün həll
  • Lifecycle-aware komponentləri görünüş məhv edildikdə abunəlikləri avtomatik ləğv edir

Yaddaş sızması və tətbiqin şişməsi nədir?

Yaddaş sızması (memory leak) — tətbiqə artıq lazım olmayan bir obyektin, kök dəstindən (GC Root) aktiv istinad olduğu üçün yaddaşda qalmağa davam etdiyi vəziyyət. Zibil toplayıcı belə bir obyekti canlı hesab edir və onu silmir.

Yaddaşın şişməsi (memory bloat) — tətbiqin cari tapşırıqları yerinə yetirmək üçün lazım olduğundan daha çox yaddaş istehlak etdiyi daha geniş bir problemdir. Səbəblər: həddindən artıq keşləmə, obyektlərin təkrarlanması, optimal olmayan məlumat strukturları və yaddaş parçalanması.

Android tətbiqləri üçün məhdud yaddaş ayrılır (adətən cihazdan və ƏS versiyasından asılı olaraq 64-512 MB). iOS məhdudiyyəti daha az sərtdir, lakin sistem limitə yaxınlaşdıqda xəbərdarlıq göndərir.

XüsusiyyətAndroidiOS
Yaddaş limiti64-512 MB (cihazdan asılıdır)Qeyri-aşkar (sistem)
Zibil toplanmasıART (Concurrent, Compact)ARC (Automatic Reference Counting)
Sızma mexanizmiGC Root istinadlarıRetain cycles (güclü istinad dövrələri)
NəticəOutOfMemoryErrorYaddaş xəbərdarlığı → dayandırma

Facebook Engineering Blog məlumatlarına görə, yaddaş sızmaları mobil tətbiqlərdə crash hesabatlarının təxminən ~15%-nin səbəbidir. Androiddə buna yaddaş çatışmazlığı zamanı tez-tez GC fasilələri səbəbindən ANR da əlavə olunur.

Android və iOS-da tipik yaddaş sızması nümunələri

Activity-ə statik istinad — Android sızmalarının klassikası. Statik sahə və ya sinqlton Activity-yə istinad saxlayırsa, sinqlton canlı olduğu müddətcə finish()-dən sonra belə GC tərəfindən toplanmayacaq. Activity View hierarchy, resurslar və Context-i ehtiva edən ağır bir obyektdir.

kotlin
object LeakHolder {
    var activityRef: Activity ?= null // sizma: Activity-yə statik istinad
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle ?= null) {
        super.onCreate(savedInstanceState)
        LeakHolder.activityRef = this // ❌ MainActivity heç vaxt GC tərəfindən toplanmayacaq
    }
}

Anonim siniflər və lambdalar — gizli şəkildə xarici sinfə istinad saxlayır. Runnable və ya Callback xarici xidmətə ötürülərsə və Activity məhv edilərsə, anonim sinif obyekti hələ də növbədə qalır və Activity-nin zibil toplanmasına getməsinə mane olur.

  • Handler gecikmə ilə — Activity məhv edilibsə, lakin Handler.postDelayed hələ icra olunmayıbsa, Activity sızır
  • Thread və AsyncTask — ekran döndərildikdə Activity yenidən yaradılır, köhnə Thread isə köhnə Activity-yə istinad saxlayır
  • Retrofit/Callback — anonim Callback presenter və ya fragment-ə istinad saxlayır
  • Müşahidəçilər (Observers) — onDestroy zamanı ləğv edilməmiş LiveData və ya RxJava abunəlikləri

iOS-da əsas problem retain cycles-dır: iki obyekt bir-birinə güclü istinadlar saxlayır və ARC heç biri üçün istinad sayını sıfırlaya bilmir. Tipik hal: self-i güclü şəkildə tutan closure və self-in closure-a istinad saxlaması.

Yaddaş sızmalarını necə aşkar etmək olar?

LeakCanary — Androiddə avtomatik sızma aşkarlanması üçün Square kitabxanası. Activity və ya Fragment məhv edildikdən sonra obyektin GC tərəfindən toplanıb-toplanmadığını yoxlayır. Əgər yoxsa — heap dump edir və sızma trace-ni göstərir.

kotlin
// LeakCanary 2.x — Application vasitəsilə avto-inteqrasiya
class ExampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // LeakCanary debug qurmasında avtomatik quraşdırılır
        // ContentProvider vasitəsilə — sıfır kod quraşdırması
    }
}

// Məcburi yoxlama çağırışı
AppWatcher.objectWatcher.watch(watchedObject, "leak description")

Android Studio Profiler — real vaxtda yaddaşı izləmək üçün quraşdırılmış alət. Heap dump yazmağa, şübhəli obyektləri (Retained Size > 1 MB) tapmağa və hər bir obyektə qədər GC root yolunu izləməyə imkan verir.

iOS üçün Xcode Memory Graph Debugger istifadə edin. O, yaddaşdakı obyektlərin qrafikini vizuallaşdırır, retain cycles göstərir və dairəvi istinadları dərhal aşkar etməyə imkan verir. Uzunmüddətli izləmə üçün Instruments > Allocations da mövcuddur.

Sızmaların qarşısının alınması strategiyaları

WeakReference — zibil toplanmasına mane olmamalı olan istinadlar üçün əsas mexanizm. GC obyekti silmək qərarına gələrsə, WeakReference null qaytarır. Geri çağırışlar, dinləyicilər və fon iplərindən UI komponentlərinə istinadlar üçün istifadə olunur.

Lifecycle-aware komponentləri — Android Jetpack-də (Lifecycle, LiveData, Flow, coroutines) tətbiq edilmiş memarlıq yanaşması. Abunəliklər onDestroy zamanı avtomatik ləğv edilir ki, bu da əsas sızma sinfini aradan qaldırır.

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() zamanı avtomatik ləğv olunur
        }
    }
}

viewModelScopelifecycleScope — Android-də həyat dövrü hadisəsi zamanı ləğv edilən quraşdırılmış CoroutineScope-lardır. Bu, müasir Android inkişafında ən çox yayılmış ssenari olan korutinlar vasitəsilə sızmaları aradan qaldırır.

  • İstifadə etməyin Context, Activity, View və ya Fragment-ə statik istinadlar
  • Ləğv edin bütün RxJava abunəliklərini disposeBag / CompositeDisposable ilə onDestroy zamanı
  • İstifadə edin [weak self] / [unowned self] iOS closure-larında retain cycles qarşısını almaq üçün
  • Yoxlayın Bitmap və böyük obyektləri — onlar təkrar emal edilməli və ya sıfırlanmalıdır

Yaddaş profilləmə alətləri

Memory Profiler in Android Studio — yaddaşı izləmək üçün əsas alət. Canlı ayırmaları, yaddaş şəkillərini, növlərə görə obyektlərin sayını göstərir. Dump yazmağa və şübhəli obyektləri tapmaq üçün MAT (Memory Analyzer Tool) ilə təhlil etməyə imkan verir.

Eclipse MAT — yaddaş dump-ları üçün masaüstü analizator. Android Studio-dan HPROF faylı yükləndikdən sonra MAT dominator ağacı qurur, hər bir obyektin retain ölçüsünü göstərir və Leak Suspects Report vasitəsilə şübhəli sızmaların avtomatik təhlilini təklif edir.

Xcode Memory Graph — retain cycles üçün vizual debugger. Memory Graph Debugger düyməsini kliklədikdə Xcode tətbiqi dayandırır, yaddaşdakı obyektlərin tam qrafikini qurur və retain cycles qırmızı rənglə vurğulayır.

AlətPlatformaXüsusiyyət
LeakCanaryAndroidMəhv edildikdən sonra avtomatik sızma aşkarlanması
Memory ProfilerAndroid StudioHeap dump + canlı ayırmalar
Eclipse MATAndroidDominator ağacı, Leak Suspects Report
Memory GraphiOS (Xcode)Retain cycles vizuallaşdırıcısı

Google I/O 2023 məlumatlarına görə, debug qurmalarında LeakCanary istifadə edən tətbiqlər tətbiqdən sonra ilk 2 ay ərzində yaddaşla bağlı crash-ların sayını 30-50% azaldır. LeakCanary-nin layihəyə onboarding mərhələsində əlavə edilməsi tövsiyə olunur.

Tez-tez verilən suallar

Yaddaş sızması şişmədən nə ilə fərqlənir?

Sızma — kod üçün əlçatmaz olan, lakin aktiv istinadlar səbəbindən GC tərəfindən silinməyən obyektlər. Şişmə — tətbiqin məntiqi olaraq lazım olan, lakin həddindən artıq miqdarda obyektləri yaddaşda saxlaması (məsələn, 80 MB ağırlığında işləyən tətbiqdə 50 MB keş). Şişmə memarlıq yolu ilə müalicə olunur, sızma isə istinadların düzgün idarə edilməsi ilə.

LeakCanary sızmaları necə tapır?

LeakCanary ObjectWatcher istifadə edir — onDestroy() Activity-dən sonra Activity-yə WeakReference yaradır və GC işə salır. Əgər 5 saniyədən sonra WeakReference təmizlənməzsə, LeakCanary heap dump edir, GC Root-dan obyektə qədər ən qısa istinad zəncirini təhlil edir və fayl adı və kod sətri ilə dəqiq sızma stackini göstərir.

Niyə Bitmap tez-tez OutOfMemoryError verir?

Bitmap Java yaddaşından kənarda, native yaddaşda (native heap) yer tutur. Bir Bitmap-in ölçüsü = en × hündürlük × 4 bayt (ARGB_8888). 12 MP foto (4000×3000) 48 MB yer tutur. Android native yaddaşı vaxtında boşalda bilməz, bu da bir neçə Bitmap yığıldıqda kifayət qədər Java yaddaşı olsa belə OOM-a səbəb olur.

iOS-da retain cycle nədir?

Retain cycle — ARC-də iki obyektin bir-birinə güclü istinadlar saxladığı və istinad sayının heç vaxt sıfıra çatmadığı vəziyyət. Tipik nümunə: ViewController-in closure-a güclü istinadı və closure-un self-i güclü tutması. Həll: closure-larda [weak self] və ya [unowned self] istifadə edin.

Android-də maksimum yaddaş ölçüsü nə qədərdir?

Yaddaş ölçüsü cihazdan və Android versiyasından asılıdır. Köhnə cihazlar üçün (API 15-24) — 64-128 MB. Müasir cihazlar üçün (API 25+) — 256-512 MB. Dəqiq dəyəri ActivityManager.getMemoryClass() vasitəsilə əldə etmək olar. Böyük tətbiqlər (oyunlar, redaktorlar) üçün manifestdə largeHeap=true var, 1 GB-a qədər verir.

Xülasə

  • Yaddaş sızması — kök dəstindən aktiv istinad səbəbindən GC tərəfindən silinməyən obyekt; şişmə — aşkar sızmalar olmadan həddindən artıq yaddaş istehlakı
  • Statik istinadlar Activity, Context, View-ə — Android-də sızmaların bir nömrəli səbəbi; həll — WeakReference və ya Application Context
  • Anonim siniflər və lambdalar gizli şəkildə xarici sinfə istinad saxlayır; ləğv edilməmiş callbacklər — ikinci ən çox yayılmış səbəb
  • LeakCanary — Android-də avtomatik sızma aşkarlanması standartı; inteqrasiya 5 dəqiqə çəkir və crash nisbətini 30-50% azaldır
  • lifecycleScope və viewModelScope korutinları destroy zamanı avtomatik ləğv edir, bütün bir sızma sinfini aradan qaldırır
  • Retain cycles iOS-da closure və delegate-lərdə weak/unowned self ilə həll olunur
  • Yaddaşı profilləyin hər sprintdə ən azı bir dəfə — MAT və ya Memory Graph ilə heap dump code review-in bir hissəsi olmalıdır

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun