Heap Dump (heaps dumpi) — ilovaning dinamik xotirasining barcha tirik obyektlar haqida to'liq ma'lumotni o'z ichiga olgan surati: ularning sinflari, o'lchamlari, o'zaro havolalari va ildiz tugunlaridan (GC roots) erishish imkoniyati. Heap Dump xotira oqishlarini tahlil qilish va resurs sarfini optimallashtirishning asosiy vositasidir. Android Developers ma'lumotlariga ko'ra, heap dump tahlili xotira oqishlarining 95% gacha aniqlash imkonini beradi, jumladan tsiklik havolalar, unutilgan listenerlar va bo'shatilmagan statik havolalar.
Asosiy fikrlar
Heap dump virtual mashinaning heaps (heap) to'liq dumi hisoblanadi — barcha dinamik yaratilgan obyektlar joylashadigan xotira maydoni. Java va Kotlin-da bu Android-dagi Dalvik/ART, Swift va Objective-C-da iOS-dagi ARC boshqariladigan heapsdir. Heap dump har bir obyektni, uning sinfini, hajmini, maydonlarini, boshqa obyektlarga havolalarni va GC roots-dan (stek o'zgaruvchilari, statik maydonlar, JNI havolalari) erishish bayroqlarini qayd etadi.
Heap dumpning asosiy maqsadi xotira oqishlarini aniqlashdir. Oqish ilova endi kerak bo'lmagan obyektlarga havolalarni ushlab turishda davom etganda, ularning garbage collector (yoki ARC orqali bo'shatilishi) tomonidan yig'ilishiga to'sqinlik qilganda yuzaga keladi. Odatdagi sabablar: activity yo'q qilinganda ro'yxatdan chiqarilmagan hodisa listenerlari; kontekstga havolalari bo'lgan singltonlar; self-ni tutib oluvchi yopilishlar (closures); ma'lumotlar o'chirilmasdan qo'shiladigan statik kolleksiyalar. Heap dump aniq tasvirni beradi: qaysi obyektlar «tirik», qaysilari ortiqcha va ularga aynan kim havola qilmoqda.
Google I/O ma'lumotlariga ko'ra, Android ilovalarining crash hisobotlarining 60% dan ortig'i OutOfMemoryError bilan bog'liq va 80% hollarda asosiy sabab heap dump orqali aniqlanadigan xotira oqishidir. iOS ilovalari uchun vaziyat o'xshash: retain cycles sababli oqishlar Xcode-da Allocations instrumenti orqali aniqlanadigan nosozliklarning keng tarqalgan sabablaridan biridir.
Heap dump quyidagi alomatlarda bajarilishi kerak: ilova takrorlanuvchi harakatlarda (ekranlar orasida oldinga-orqaga o'tish) xotirani chiziqli ravishda sarflaydi; ekran ishini tugatgandan so'ng xotira boshlang'ich darajaga qaytmaydi; OutOfMemoryError yoki iOS-da memory warning ogohlantirishlari yuzaga keladi; ilova xotira chegarasidan oshib ketganligi sababli tugatiladi (EXC_RESOURCE_RESOURCE iOS-da). Muntazam heap dump yig'ish Instagram va Spotify kabi yirik mobil loyihalarda muhandislik madaniyatining bir qismidir.
Android Studio real vaqtda heap dump olish uchun o'rnatilgan vosita — Memory Profiler-ni taqdim etadi. View → Tool Windows → Profiler orqali mavjud. Ilova ishga tushirilgandan so'ng, sessiyani tanlang, Memory yorlig'iga o'ting va Dump Java Heap tugmasini bosing. Android Studio ilovani to'xtatadi, ART heaps dumni amalga oshiradi va natijani tahlil uchun yuklaydi. Dum fayli .hprof formatiga ega — aksariyat xotira analizatorlari bilan mos keladigan HPROF standarti.
Dum yuklangandan so'ng, Android Studio ustunlari bo'lgan obyektlar jadvalini ko'rsatadi: Allocations (namunalar soni), Native Size (ART heapsidan tashqari xotira), Shallow Size (obyektning o'z xotirasi), Retained Size (butun pastki grafi bilan obyekt xotirasi). Sinf nomi bo'yicha filtrlash, retained size bo'yicha tartiblash va paketlar bo'yicha qidirish muammoli joylarni tez topishga imkon beradi.
// Odatiy oqish — onDestroy-da ro'yxatdan chiqarilmagan 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) o'tkazib yuborilgan
// → Activity GC tomonidan yig'ilmaydi, heap dump oqishni ko'rsatadi
}
}
Dominator Tree yorlig'i eng ko'p xotirani ushlab turgan obyektlarni ko'rsatadi. Agar obyekt dominator tree-dan o'chirilsa, u ushlab turgan barcha xotira yig'ish uchun mavjud bo'ladi. Bu asosiy vositadir: minglab obyektlarni ko'rib chiqish o'rniga, xotiraning 80-90% ni boshqaradigan 10-20 obyektga e'tibor qaratasiz. Google ma'lumotlariga ko'ra, dominator tree tahlili oqish nuqtasini topishning eng samarali usuli bo'lib, tahlil vaqtini soatlardan daqiqalarga qisqartiradi.
Xcode Instruments heap dump bilan ishlash uchun ikkita vositani taqdim etadi: Allocations — real vaqtda sarf grafigi bilan heaps dumni olish; Leaks — retain cycles tahlili orqali avtomatik oqish qidiruvi. Allocations heapsdagi barcha obyektlarni, ularning hajmini, yaratilish (allocations) va bo'shatilish (deallocations) sonini ko'rsatadi. Muayyan sinf uchun yaratilish va bo'shatilish soni o'rtasidagi farq potentsial oqishni ko'rsatadi.
Allocations-da heap dump olish Snapshot Memory tugmasi bilan amalga oshiriladi — vosita ilovani to'xtatadi va to'liq dum oladi. Shundan so'ng standart ko'rinishlar mavjud: sinflar bo'yicha obyektlar ro'yxati, har bir obyekt uchun chaqiruv daraxti (call tree) va hisobot generatori. Android Studio-dan farqli o'laroq, Xcode .hprof ishlatmaydi, ma'lumotlarni Instruments bilan mos keladigan o'z .trace formatida saqlaydi.
// Odatiy iOS oqishi — yopilish orqali retain cycle
class NetworkManager {
var onComplete: ((Data) -> Void)?
func startRequest() {
// ❌ Yopilish self-ni tutib oladi — retain cycle
onComplete = { data in
self.process(data)
}
}
func process(_ data: Data) {}
}
Leaks instrumenti havola grafi tahlili orqali retain cycles va oqishlarni avtomatik aniqlaydi. Oqayotgan obyektlarni binafsha belgi bilan belgilaydi va ildizga (GC root) yo'lni ko'rsatadi. Retain cycleni bartaraf etish uchun yopilishda [weak self] yoki [unowned self] qo'shish kifoya. Leaks instrumentining muntazam ishga tushirilishi Swift-dan iOS ishlanmasi uchun foydalanadigan jamoalarda CI-ning majburiy bosqichidir.
// Tuzatish — self-ga zaif havola
onComplete = { [weak self] data in
guard let self else { return }
self.process(data)
}
Heap dumpning to'g'ri tahlili uchun uchta asosiy ko'rsatkichni tushunish kerak. Shallow size — obyekt tomonidan bevosita egallangan xotira hajmi: uning maydonlari, sarlavha (header) va tekislash. Odatdagi Java/Kotlin obyekti uchun shallow size 16-40 baytni tashkil qiladi. Retained size — obyektning shallow size-i va faqat shu obyekt orqali mavjud bo'lgan barcha obyektlarning umumiy shallow size-i (ya'ni uni o'chirishdan keyin axlatga aylanadi). Aynan retained size obyektning xotira sarfiga real ta'sirini ko'rsatadi.
| Ko'rsatkich | Tavsif | Misol |
|---|---|---|
| Shallow size | Obyektning baytlardagi hajmi | Bitmap (100×100) = 40 016 B |
| Retained size | Shallow size + ushlab turgan hamma narsa | View Tree bilan Activity = 2-5 MB |
| Deep size | Retained size + boshqa graflardan ichki obyektlar | Adapter bilan ScrollView = 10-50 MB |
Dominator tree — har bir obyekt o'z «dominant»iga — uning mavjudligini boshqaradigan obyektga havola qiladigan struktura. Agar dominant o'chirilsa, uning butun pastki daraxtidagi obyektlar axlatga aylanadi. Dominator tree tahlili eng ko'p xotirani ushlab turgan obyektni topishning eng tezkor usulidir. Eclipse MAT (Memory Analyzer Tool) ma'lumotlariga ko'ra, oqishlarning 90% 5 daqiqa ichida top-20 dominator tree-ni ko'rib chiqish orqali aniqlanadi.
Heap dump orqali oqish tahlili jarayoni bir necha bosqichdan iborat. 1-bosqich: xotirani bo'shatishi kerak bo'lgan harakatni bajaring (ekranni yoping, operatsiyani tugating). 2-bosqich: GC-ni chaqiring (Android-da System.gc(), Xcode-da majburiy snapshot) va heap dump qiling. 3-bosqich: yo'q qilinishi kerak bo'lgan obyektlarni toping (masalan, finish-dan keyin Activity namunasi). 4-bosqich: shubhali obyekt uchun Path to GC Roots ni bajaring — obyektni tirik ushlab turgan havolalar zanjiri. Zanjirdagi oxirgi havola oqishning sababidir.
Path to GC Roots funksiyasi Android Studio Profiler, Eclipse MAT va Xcode Instruments-da mavjud. GC root-dan muammoli obyektgacha eng qisqa havola zanjirini ko'rsatadi. Zaif (weak) va yumshoq (soft) havolalarni chiqarib tashlab, faqat kuchli (strong) havolalarni — ya'ni yig'ilishga to'sqinlik qiladiganlarni olasiz. Square Engineering statistikasiga ko'ra, Android ilovalaridagi oqishlarning 70% faqat ikkita naqshdan kelib chiqadi: Activity yoki Context-ga statik havolalar va ro'yxatdan o'tgan, ammo ro'yxatdan chiqarilmagan listenerlar.
// Statik havola orqali oqish namunasi
object AppCache {
private val cache = mutableMapOf<String, Any>()
fun storeActivityReference(activity: Activity) {
cache["current_activity"] = activity // ❌ Oqish!
}
}
// Tuzatish: zaif havola
object AppCacheFixed {
private val cache = mutableMapOf<String, WeakReference<Any>>()
}
Comparison mode texnikasi — oqishlarni topishning eng samarali usullaridan biridir. Takrorlanuvchi harakatdan oldin va keyin heap dump oling (masalan, ekranga besh marta o'tish va qaytish). Asosiy sinflarning namuna sonini solishtiring: agar Activity soni ortgan bo'lsa, lekin barcha aktivliklar yopilgan bo'lsa — bu oqish. Android Studio va Eclipse MAT farqlarni ajratib ko'rsatish bilan dumlarni avtomatik solishtirishni qo'llab-quvvatlaydi. Google ma'lumotlariga ko'ra, dum solishtirish effektning to'planishi hisobiga bir martalik tahlilda ko'rinmaydigan oqishlarni topishga imkon beradi.
Real loyihalarda heap dump tahlili asosida xotira optimallashtirishning tasdiqlangan amaliyotlari ishlab chiqilgan. WeakReference dan foydalaning keshlar, qayta chaqiruvlar va uzoq muddatli obyektlarda kontekstga havolalar uchun. Listenerlarni ro'yxatdan chiqaring Android uchun onPause/onDestroy va iOS uchun deinit-da. Katta statik kolleksiyalardan saqlaning — agar zarur bo'lsa, o'lcham cheklovi bilan LruCache dan foydalaning. Bitmaplarni optimallashtiring: rasmlarni to'g'ri inSampleSize bilan yuklang, disk keshi bilan Glide yoki Picasso dan foydalaning.
CI ga muntazam heap dump olishni qo'shing. Instrumental UI testlarini ishga tushiradigan, asosiy foydalanuvchi stsenariylarini bajaradigan va heap dumpni baseline bilan solishtiradigan vazifani sozlang. Agar retained size baseline-dan 5% dan ko'proq oshsa, qurilish regressiya sifatida belgilanadi. Bunday yondashuv Airbnb, Uber va sifatga yuqori talablarga ega boshqa kompaniyalarda qo'llaniladi. Uber Engineering ma'lumotlariga ko'ra, CI-da heap dumpning avtomatik tahlilini joriy etish chorakda xotira bilan bog'liq xatolar sonini 70% ga kamaytirdi.
// CI-da avtomatik heap dump uchun Gradle topshirig'i namunasi
task profileMemory(type: Exec) {
commandLine 'adb', 'shell',
'am start -n com.example/.MainActivity'
// Yuklash kutilmoqda
doLast {
exec { commandLine 'adb', 'shell',
'am broadcast -a com.example.DUMP_HEAP' }
}
}
Tez-tez so'raladigan savollar
Shallow size — obyektning o'z hajmi (maydonlar + sarlavha). Retained size — obyektning va uni o'chirishdan keyin axlatga aylanadigan barcha obyektlarning hajmi. Retained size obyektning xotira sarfiga ta'sirining asosiy ko'rsatkichidir.
Android Studio Profiler orqali qurilma va jarayonni tanlang, Dump Java Heap tugmasini bosing. Muqobil — buyruq satri orqali: adb shell am dumpheap PID /sdcard/dump.hprof, so'ngra adb pull.
Heap dump barcha tirik obyektlarni o'z ichiga oladi. Agar ilova keshlar, Bitmaplar ishlatsa yoki katta ma'lumotlarni qayta ishlasa, dum yuzlab megabaytga yetishi mumkin. Sinflar bo'yicha filtrlang yoki faqat indeksni yuklash uchun Eclipse MAT dan foydalaning.
Ha, Eclipse MAT (Memory Analyzer Tool) — .hprof tahlili uchun bepul vositadan foydalaning. Dominator tree, path to GC roots, dum solishtirish va Leak Suspects Report orqali avtomatik oqish qidiruvini qo'llab-quvvatlaydi.
Dumning o'zi — ha, chunki dum yig'ish barcha oqimlarni to'xtatadi (stop-the-world). Dumsiz — yo'q. Dumni boshqariladigan sharoitda (test stendi, CI) qiling, ishlab chiqarishda emas.
Xulosa
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.