Heap Dump (yığın dumpu) — tətbiqin dinamik yaddaşının bütün canlı obyektlər haqqında tam məlumatı özündə əks etdirən şəklidir: onların sinifləri, ölçüləri, qarşılıqlı istinadları və kök qovşaqlardan (GC roots) əlçatanlığı. Heap Dump yaddaş sızmalarının təhlili və resurs istehlakının optimallaşdırılması üçün əsas vasitədir. Android Developers məlumatlarına görə, heap dump təhlili yaddaş sızmalarının 95%-ə qədərini aşkar etməyə imkan verir, o cümlədən tsiklik istinadlar, unudulmuş listenerlər və azad olunmamış statik istinadlar.
Əsas məqamlar
Heap dump virtual maşının yığınının (heap) tam dumpudur — bütün dinamik yaradılan obyektlərin yerləşdiyi yaddaş sahəsi. Java və Kotlin-də bu Android-də Dalvik/ART, Swift və Objective-C-də iOS-da ARC ilə idarə olunan yığındır. Heap dump hər bir obyekti, onun sinfini, ölçüsünü, sahələrini, digər obyektlərə istinadları və GC roots-dan (stack dəyişənləri, statik sahələr, JNI istinadları) əlçatanlıq bayraqlarını qeyd edir.
Heap dump-un əsas məqsədi yaddaş sızmalarının aşkarlanmasıdır. Sızma o zaman yaranır ki, tətbiq artıq lazım olmayan obyektlərə istinadları saxlamağa davam edir, onların zibil yığıcı (və ya ARC vasitəsilə azad edilməsinin) qarşısını alır. Tipik səbəblər: activity məhv edilərkən qeydiyyatdan çıxarılmayan hadisə listenerləri; kontekstə istinadları olan sinqltonlar; self-i tutan domkniyələr (closures); məlumatların silinmədən əlavə edildiyi statik kolleksiyalar. Heap dump dəqiq mənzərə verir: hansı obyektlər "canlıdır", hansılar artıqdır və onlara məhz kim istinad edir.
Google I/O məlumatlarına görə, Android tətbiqlərinin crash hesabatlarının 60%-dən çoxu OutOfMemoryError ilə bağlıdır və 80% hallarda əsas səbəb heap dump vasitəsilə aşkar edilən yaddaş sızmasıdır. iOS tətbiqləri üçün vəziyyət oxşardır: retain cycle səbəbindən sızmalar Xcode-da Allocations instrumenti vasitəsilə aşkar edilən qəzaların ümumi səbəblərindəndir.
Heap dump aşağıdakı simptomlarda yerinə yetirilməlidir: tətbiq təkrarlanan hərəkətlərdə (ekranlar arasında irəli-geri keçidlər) yaddaşı xətti olaraq istehlak edir; ekran işini bitirdikdən sonra yaddaş ilkin səviyyəyə qayıtmır; OutOfMemoryError və ya iOS-da memory warning xəbərdarlıqları yaranır; tətbiq yaddaş limitini aşdığı üçün dayanır (EXC_RESOURCE_RESOURCE iOS-da). Müntəzəm heap dump toplamaq Instagram və Spotify kimi böyük mobil layihələrdə mühəndislik mədəniyyətinin bir hissəsidir.
Android Studio real vaxtda heap dump ələ keçirmək üçün daxili alət olan Memory Profiler-i təqdim edir. View → Tool Windows → Profiler vasitəsilə əlçatandır. Tətbiq işə salındıqdan sonra seans seçin, Memory sekmesine keçin və Dump Java Heap düyməsini sıxın. Android Studio tətbiqi dayandırır, ART yığın dumpunu yerinə yetirir və nəticəni analiz üçün yükləyir. Dump faylı .hprof formatına malikdir — əksər yaddaş analizatorları ilə uyğun olan HPROF standartı.
Dump yükləndikdən sonra Android Studio sütunları olan obyekt cədvəlini göstərir: Allocations (nümunələrin sayı), Native Size (ART yığınından kənar yaddaş), Shallow Size (obyektin öz yaddaşı), Retained Size (bütün altqrafı ilə obyektin yaddaşı). Sinif adına görə filtrləmə, retained size-a görə sıralama və paketlər üzrə axtarış problemli sahələri tez tapmağa imkan verir.
// Tipik sızma — onDestroy-də qeydiyyatdan çıxarılmayan listener
class MainActivity : AppCompatActivity() {
private val sensorManager by lazy {
getSystemService(SENSOR_SERVICE) as SensorManager
}
private val listener = MySensorListener()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sensorManager.registerListener(listener,
sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onDestroy() {
super.onDestroy()
// ❌ sensorManager.unregisterListener(listener) buraxılıb
// → Activity GC tərəfindən yığılmayacaq, heap dump sızmanı göstərəcək
}
}
Dominator Tree sekmesi ən çox yaddaş saxlayan obyektləri göstərir. Əgər obyekt dominator tree-dən silinərsə, onun saxladığı bütün yaddaş zibil yığımı üçün əlçatan olur. Bu əsas vasitədir: minlərlə obyektə baxmaq əvəzinə, yaddaşın 80-90%-ni idarə edən 10-20 obyektə diqqət yetirirsiniz. Google-a görə, dominator tree analizi sızma nöqtəsini tapmaq üçün ən təsirli üsuldur və analiz müddətini saatlardan dəqiqələrə endirir.
Xcode Instruments heap dump ilə işləmək üçün iki alət təqdim edir: Allocations — real vaxtda istehlak qrafiki ilə yığın dumpunun ələ keçirilməsi; Leaks — retain cycles analizi vasitəsilə avtomatik sızma axtarışı. Allocations yığındakı bütün obyektləri, onların ölçüsünü, yaradılma (allocations) və azad edilmə (deallocations) sayını göstərir. Müəyyən bir sinif üçün yaradılma və azad edilmə sayı arasındakı fərq potensial sızmanı göstərir.
Allocations-da heap dump ələ keçirmək Snapshot Memory düyməsi ilə yerinə yetirilir — alət tətbiqi dayandırır və tam dump götürür. Bundan sonra standart görünüşlər mövcuddur: siniflər üzrə obyekt siyahısı, hər bir obyekt üçün çağırış ağacı (call tree) və hesabat generatoru. Android Studio-dan fərqli olaraq, Xcode .hprof istifadə etmir, məlumatları Instruments ilə uyğun olan öz .trace formatında saxlayır.
// Tipik iOS sızması — domkniyə vasitəsilə retain cycle
class NetworkManager {
var onComplete: ((Data) -> Void)?
func startRequest() {
// ❌ Domkniyə self-i tutur — retain cycle
onComplete = { data in
self.process(data)
}
}
func process(_ data: Data) {}
}
Leaks instrumenti istinad qrafikinin təhlili vasitəsilə retain cycles və sızmaları avtomatik aşkar edir. Sızan obyektləri bənövşəyi işarə ilə qeyd edir və kökə (GC root) yolu göstərir. Retain cycle aradan qaldırmaq üçün domkniyədə [weak self] və ya [unowned self] əlavə etmək kifayətdir. Leaks instrumentinin müntəzəm işə salınması Swift-dən iOS inkişafı üçün istifadə edən komandalarda CI-nin məcburi mərhələsidir.
// Düzəliş — self-ə zəif istinad
onComplete = { [weak self] data in
guard let self else { return }
self.process(data)
}
Heap dump-un düzgün təhlili üçün üç əsas metrikanı başa düşmək lazımdır. Shallow size — birbaşa obyektin tutduğu yaddaşın həcmi: onun sahələri, başlıq (header) və düzəltmə. Tipik Java/Kotlin obyekti üçün shallow size 16-40 bayt təşkil edir. Retained size — obyektin shallow size-i üstəgəl yalnız bu obyekt vasitəsilə əlçatan olan bütün obyektlərin ümumi shallow size-i (yəni onun silinməsindən sonra zibilə çevriləcək). Məhz retained size obyektin yaddaş istehlakına real təsirini göstərir.
| Metrika | Təsvir | Nümunə |
|---|---|---|
| Shallow size | Obyektin baytlarla ölçüsü | Bitmap (100×100) = 40 016 B |
| Retained size | Shallow size + saxladığı hər şey | View Tree ilə Activity = 2-5 MB |
| Deep size | Retained size + digər qraflardan iç-içə obyektlər | Adapter ilə ScrollView = 10-50 MB |
Dominator tree — hər bir obyektin öz "dominant"ına — onun əlçatanlığını idarə edən obyektə istinad etdiyi strukturdur. Əgər dominant silinərsə, onun bütün alt ağac obyektləri zibilə çevrilir. Dominator tree analizi ən çox yaddaş saxlayan obyekti tapmaq üçün ən sürətli üsuldur. Eclipse MAT (Memory Analyzer Tool) məlumatlarına görə, sızmaların 90%-i 5 dəqiqə ərzində top-20 dominator tree-ə baxmaqla aşkar edilir.
Heap dump vasitəsilə sızma analizi prosesi bir neçə addımdan ibarətdir. Addım 1: yaddaşı azad etməli olan hərəkəti yerinə yetirin (ekranı bağlayın, əməliyyatı bitirin). Addım 2: GC-ni çağırın (Android-də System.gc(), Xcode-da məcburi snapshot) və heap dump edin. Addım 3: məhv edilməli olan obyektləri tapın (məsələn, finish-dən sonra Activity nümunəsi). Addım 4: şübhəli obyekt üçün Path to GC Roots icra edin — obyekti canlı saxlayan istinadlar zənciri. Zəncirdəki son istinad sızmanın səbəbidir.
Path to GC Roots funksiyası Android Studio Profiler, Eclipse MAT və Xcode Instruments-da mövcuddur. GC root-dan problemli obyektə qədər ən qısa istinad zəncirini göstərir. Zəif (weak) və yumşaq (soft) istinadları istisna etməklə yalnız güclü (strong) istinadları — yəni zibil yığımına mane olanları əldə edirsiniz. Square Engineering statistikasına görə, Android tətbiqlərində sızmaların 70%-i cəmi iki naxışdan qaynaqlanır: Activity və ya Context-ə statik istinadlar və qeydiyyatdan keçmiş lakin qeydiyyatdan çıxarılmayan listenerlər.
// Statik istinad vasitəsilə sızma nümunəsi
object AppCache {
private val cache = mutableMapOf<String, Any>()
fun storeActivityReference(activity: Activity) {
cache["current_activity"] = activity // ❌ Sızma!
}
}
// Düzəliş: zəif istinad
object AppCacheFixed {
private val cache = mutableMapOf<String, WeakReference<Any>>()
}
Comparison mode texnikası sızmaları tapmaq üçün ən təsirli üsullardan biridir. Təkrarlanan hərəkətdən əvvəl və sonra heap dump edin (məsələn, ekrana beş keçid və geri). Əsas siniflərin nümunə sayını müqayisə edin: əgər Activity sayı artıbsa, lakin bütün aktivliklər bağlanıbsa — bu sızmadır. Android Studio və Eclipse MAT fərqləri vurğulamaqla dump-ların avtomatik müqayisəsini dəstəkləyir. Google-a görə, dump müqayisəsi effektin toplanması hesabına birdəfəlik analizdə görünməyən sızmaları tapmağa imkan verir.
Real layihələrdə heap dump təhlili əsasında yaddaş optimallaşdırmasının sübut edilmiş təcrübələri işlənib hazırlanmışdır. WeakReference istifadə edin keşlər, geri çağırışlar və uzunömürlü obyektlərdə kontekstə istinadlar üçün. Listenerləri qeydiyyatdan çıxarın Android üçün onPause/onDestroy və iOS üçün deinit-də. Böyük statik kolleksiyalardan qaçın — əgər zəruridirsə, ölçü məhdudiyyəti olan LruCache istifadə edin. Bitmap-ları optimallaşdırın: şəkilləri düzgün inSampleSize ilə yükləyin, disk keşi ilə Glide və ya Picasso istifadə edin.
CI-ya müntəzəm heap dump ələ keçirməni daxil edin. Instrumentalı UI testləri işə salan, əsas istifadəçi ssenarilərini yerinə yetirən və heap dump-u baseline ilə müqayisə edən tapşırıq qurun. Əgər retained size baseline-dan 5%-dən çox artarsa, quruluş reqressiya kimi qeyd olunur. Bu yanaşma Airbnb, Uber və keyfiyyətə yüksək tələbləri olan digər şirkətlərdə tətbiq olunur. Uber Engineering məlumatlarına görə, CI-da heap dump-un avtomatik təhlilinin tətbiqi rübdə yaddaşla bağlı səhvlərin sayını 70% azaldıb.
// CI-da avtomatik heap dump üçün Gradle tapşırığı nümunəsi
task profileMemory(type: Exec) {
commandLine 'adb', 'shell',
'am start -n com.example/.MainActivity'
// Yükləmə gözlənilir
doLast {
exec { commandLine 'adb', 'shell',
'am broadcast -a com.example.DUMP_HEAP' }
}
}
Tez-tez verilən suallar
Shallow size — obyektin öz ölçüsü (sahələr + başlıq). Retained size — obyektin və onun silinməsindən sonra zibilə çevriləcək bütün obyektlərin ölçüsü. Retained size obyektin yaddaş istehlakına təsirinin əsas göstəricisidir.
Android Studio Profiler vasitəsilə cihazı və prosesi seçin, Dump Java Heap düyməsini sıxın. Alternativ olaraq — komanda sətri ilə: adb shell am dumpheap PID /sdcard/dump.hprof, sonra adb pull.
Heap dump bütün canlı obyektləri əhatə edir. Əgər tətbiq keşlər, bitmap-lar istifadə edirsə və ya böyük məlumatları emal edirsə, dump yüzlərlə meqabayta çata bilər. Siniflər üzrə filtrləyin və ya yalnız indeksi yükləmək üçün Eclipse MAT istifadə edin.
Bəli, Eclipse MAT (Memory Analyzer Tool) — .hprof analizi üçün pulsuz vasitədir. Dominator tree, path to GC roots, dump müqayisəsi və Leak Suspects Report vasitəsilə avtomatik sızma axtarışını dəstəkləyir.
Dump-un özü — bəli, çünki dump yığımı bütün ipləri dayandırır (stop-the-world). Dump olmadan — yox. Dump-u idarə olunan şəraitdə (test stendi, CI) edin, prodakşnda yox.
Nəticə
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.
Həm də oxuyun