Heap Dump (yığın dökümü), bir uygulamanın dinamik belleğinin, tüm canlı nesneler hakkında eksiksiz bilgi içeren bir anlık görüntüsüdür: sınıfları, boyutları, karşılıklı referansları ve GC köklerinden erişilebilirlik. Heap Dump, bellek sızıntılarını analiz etmek ve kaynak tüketimini optimize etmek için birincil araçtır. Android Developers'a göre, heap dump analizi, döngüsel referanslar, unutulan dinleyiciler ve serbest bırakılmamış statik referanslar dahil olmak üzere bellek sızıntılarının %95'ine kadarını tespit edebilir.
Önemli Noktalar
Heap dump, sanal makine yığınının tam bir dökümüdür — tüm dinamik olarak oluşturulan nesnelerin bulunduğu bellek alanı. Java ve Kotlin'de Android'deki Dalvik/ART yığınıdır, Swift ve Objective-C'de iOS'taki ARC tarafından yönetilen yığındır. Bir heap dump, her nesneyi, sınıfını, boyutunu, alanlarını, diğer nesnelere referanslarını ve GC köklerinden erişilebilirlik işaretlerini yakalar.
Bir heap dump'un temel amacı bellek sızıntılarını tespit etmektir. Bir sızıntı, bir uygulamanın artık ihtiyaç duyulmayan nesnelere referansları tutmaya devam etmesi ve çöp toplayıcı tarafından toplanmalarını engellemesiyle oluşur. Tipik nedenler: bir activity yok edildiğinde kaydı silinmeyen olay dinleyicileri; bağlama referansları olan singleton'lar; self'i yakalayan closure'lar; verilerin silinmeden eklendiği statik koleksiyonlar. Bir heap dump doğru bir resim sağlar: hangi nesneler “canlı”, hangileri gereksiz ve onlara tam olarak kim referans veriyor.
Google I/O'ya göre, Android uygulaması çökme raporlarının %60'ından fazlası OutOfMemoryError ile ilgilidir ve vakaların %80'inde temel neden, heap dump ile tespit edilebilen bir bellek sızıntısıdır. iOS uygulamaları için durum benzerdir: retain cycle'lardan kaynaklanan sızıntılar, Xcode'daki Allocations aracıyla tespit edilen en yaygın çökme nedenlerinden biridir.
Heap dump, aşağıdaki belirtiler ortaya çıktığında yapılmalıdır: uygulama tekrarlayan eylemler sırasında doğrusal olarak bellek tüketir; bir ekran kapatıldıktan sonra bellek temel seviyeye dönmez; OutOfMemoryError veya iOS'ta bellek uyarıları oluşur; uygulama bellek sınırını aştığı için sonlanır. Instagram ve Spotify gibi büyük mobil projelerde düzenli heap dump toplama, mühendislik kültürü protokolünün bir parçasıdır.
Android Studio, Memory Profiler sağlar — gerçek zamanlı olarak heap dump almak için yerleşik bir araç. View → Tool Windows → Profiler üzerinden erişilebilir. Uygulamayı başlattıktan sonra oturumu seçin, Memory sekmesine gidin ve Dump Java Heap'e tıklayın. Android Studio uygulamayı duraklatır, bir ART yığın dökümü gerçekleştirir ve analiz için sonucu yükler. Döküm dosyası .hprof biçimindedir — çoğu bellek analizörüyle uyumlu HPROF standardı.
Dökümü yükledikten sonra Android Studio, sütunlar içeren bir nesne tablosu görüntüler: Allocations (örnek sayısı), Native Size (ART yığını dışındaki bellek), Shallow Size (nesnenin kendi belleği), Retained Size (tüm alt grafiği dahil nesnenin belleği). Sınıf adına göre filtreleme, retained size'a göre sıralama ve paketlere göre arama, sorunlu alanları hızlıca bulmanızı sağlar.
// Tipik sızıntı — onDestroy'de kaydı silinmemiş bir dinleyici
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) eksik
// → Activity GC tarafından toplanmaz, heap dump sızıntıyı gösterir
}
}
Dominator Tree sekmesi, en fazla belleği tutan nesneleri gösterir. Bir nesne dominator tree'den kaldırılırsa, tuttuğu tüm bellek çöp toplama için kullanılabilir hale gelir. Bu önemli bir araçtır: binlerce nesneyi taramak yerine, belleğin %80–90'ını kontrol eden 10–20 nesneye odaklanırsınız. Google'a göre, dominator tree analizi bir sızıntı noktası bulmanın en etkili yoludur ve analiz süresini saatlerden dakikalara düşürür.
Xcode Instruments, heap dump ile çalışmak için iki araç sağlar: Allocations — gerçek zamanlı tüketim grafiğiyle yığın dökümü alma; Leaks — retain cycle analizi yoluyla otomatik sızıntı arama. Allocations, yığındaki tüm nesneleri, boyutlarını, oluşturma sayılarını ve serbest bırakma sayılarını görüntüler. Belirli bir sınıf için oluşturma ve serbest bırakma sayıları arasındaki fark, potansiyel bir sızıntıyı gösterir.
Allocations'ta heap dump alma, Snapshot Memory düğmesiyle yapılır — araç uygulamayı duraklatır ve tam bir döküm alır. Bundan sonra standart görünümler mevcuttur: sınıfa göre nesne listesi, her nesne için çağrı ağacı ve bir rapor oluşturucu. Android Studio'nun aksine Xcode, .hprof kullanmaz, verileri Instruments ile uyumlu kendi .trace biçiminde saklar.
// Tipik iOS sızıntısı — bir closure aracılığıyla retain cycle
class NetworkManager {
var onComplete: ((Data) -> Void)?
func startRequest() {
// ❌ Closure self'i yakalar — retain cycle
onComplete = { data in
self.process(data)
}
}
func process(_ data: Data) {}
}
Leaks aracı, referans grafiği analizi yoluyla retain cycle'ları ve sızıntıları otomatik olarak algılar. Sızdıran nesneleri mor bir simgeyle işaretler ve köke (GC root) giden yolu gösterir. Bir retain cycle'ı ortadan kaldırmak için closure yakalamasına [weak self] veya [unowned self] eklemek yeterlidir. Swift kullanan ekiplerde Leaks aracının düzenli olarak çalıştırılması, CI boru hattının zorunlu bir adımıdır.
// Düzeltme — self'e zayıf referans
onComplete = { [weak self] data in
guard let self else { return }
self.process(data)
}
Bir heap dump'u doğru analiz etmek için üç temel metriği anlamak gerekir. Shallow size, nesnenin doğrudan kapladığı bellek miktarıdır: alanları, başlığı ve hizalama. Tipik bir Java/Kotlin nesnesi için shallow size 16–40 bayttır. Retained size, nesnenin shallow size'ı artı yalnızca bu nesne üzerinden erişilebilen tüm nesnelerin toplam shallow size'ıdır. Retained size, nesnenin bellek tüketimi üzerindeki gerçek etkisini gösterir.
| Metrik | Açıklama | Örnek |
|---|---|---|
| Shallow size | Nesnenin kendi boyutu (bayt) | Bitmap (100×100) = 40.016 B |
| Retained size | Shallow size + tuttuğu her şey | View Tree ile Activity = 2–5 MB |
| Deep size | Retained size + diğer grafiklerden iç içe nesneler | Adaptörlü ScrollView = 10–50 MB |
Dominator tree, her nesnenin “efendisine” referans verdiği bir yapıdır — erişilebilirliğini kontrol eden nesne. Efendi kaldırılırsa, alt ağacındaki tüm nesneler çöp haline gelir. Dominator tree analizi, hangi nesnenin en fazla belleği tuttuğunu bulmanın en hızlı yoludur. Eclipse MAT'e göre, sızıntıların %90'ı 5 dakika içinde ilk 20 dominator tree incelenerek tespit edilir.
Heap dump ile sızıntı analizi süreci birkaç adımdan oluşur. Adım 1: belleği serbest bırakması gereken eylemi gerçekleştirin. Adım 2: GC'yi çağırın ve heap dump alın. Adım 3: yok edilmiş olması gereken nesneleri bulun. Adım 4: şüpheli nesne için Path to GC Roots'u çalıştırın — nesneyi canlı tutan referans zinciri. Zincirdeki son referans sızıntının nedenidir.
Path to GC Roots işlevi Android Studio Profiler, Eclipse MAT ve Xcode Instruments'ta mevcuttur. Bir GC kökünden sorunlu nesneye en kısa referans zincirini gösterir. Zayıf ve yumuşak referansları hariç tutarak, yalnızca toplamayı gerçekten engelleyen güçlü referansları elde edersiniz. Square Engineering'e göre, Android uygulamalarındaki sızıntıların %70'i yalnızca iki desenden kaynaklanır: Activity veya Context'e statik referanslar ve kaydedilmiş ancak kaydı silinmemiş dinleyiciler.
// Statik referans yoluyla sızıntı örneği
object AppCache {
private val cache = mutableMapOf<String, Any>()
fun storeActivityReference(activity: Activity) {
cache["current_activity"] = activity // ❌ Sızıntı!
}
}
// Düzeltme: zayıf referans
object AppCacheFixed {
private val cache = mutableMapOf<String, WeakReference<Any>>()
}
Karşılaştırma modu tekniği, sızıntıları bulmanın en etkili yöntemlerinden biridir. Tekrarlayan bir eylemden önce ve sonra heap dump alın. Anahtar sınıfların örnek sayılarını karşılaştırın: tüm activity'ler kapatılmış olmasına rağmen Activity sayısı arttıysa — bu bir sızıntıdır. Android Studio ve Eclipse MAT, farklılıkları vurgulayarak otomatik döküm karşılaştırmasını destekler. Google'a göre, döküm karşılaştırması, birikim etkisi sayesinde tek analizde görünmeyen sızıntıları bulmanızı sağlar.
Gerçek projelerdeki heap dump analizine dayanarak, kanıtlanmış bellek optimizasyonu uygulamaları geliştirilmiştir. WeakReference kullanın önbellekler, geri çağırmalar ve uzun ömürlü nesnelerde bağlam referansları için. Dinleyicilerin kaydını silin Android için onPause/onDestroy ve iOS için deinit'te. Büyük statik koleksiyonlardan kaçının — gerekliyse, boyut sınırı olan LruCache kullanın. Bitmap'leri optimize edin: görüntüleri doğru inSampleSize ile yükleyin, disk önbelleğiyle Glide veya Picasso kullanın.
CI boru hattınıza düzenli heap dump almayı dahil edin. Enstrümante UI testlerini çalıştıran, ana kullanıcı senaryolarını gerçekleştiren ve heap dump'u bir temel çizgiyle karşılaştıran bir görev ayarlayın. Retained size temel çizgiden %5'ten fazla artarsa, yapı bir gerileme olarak işaretlenir. Bu yaklaşım Airbnb, Uber ve yüksek kalite gereksinimleri olan diğer şirketlerde uygulanmaktadır. Uber Engineering'e göre, CI'da otomatik heap dump analizinin uygulanması, bellek ile ilgili hataları bir çeyrekte %70 oranında azaltmıştır.
// CI'da otomatik heap dump için Gradle görevi örneği
task profileMemory(type: Exec) {
commandLine 'adb', 'shell',
'am start -n com.example/.MainActivity'
// Yükleme bekleniyor
doLast {
exec { commandLine 'adb', 'shell',
'am broadcast -a com.example.DUMP_HEAP' }
}
}
Sıkça Sorulan Sorular
Shallow size nesnenin kendi boyutudur (alanlar + başlık). Retained size nesnenin boyutu artı kaldırıldığında çöp haline gelecek tüm nesnelerin boyutudur. Retained size, bir nesnenin bellek tüketimi üzerindeki etkisinin ana göstergesidir.
Android Studio Profiler üzerinden cihazı ve süreci seçin, Dump Java Heap'e tıklayın. Alternatif olarak komut satırı üzerinden: adb shell am dumpheap PID /sdcard/dump.hprof, ardından adb pull.
Heap dump tüm canlı nesneleri içerir. Uygulama önbellekler, Bitmap'ler kullanıyorsa veya büyük veriler işliyorsa, döküm yüzlerce megabayta ulaşabilir. Sınıflara göre filtreleyin veya yalnızca dizini yüklemek için Eclipse MAT kullanın.
Evet, Eclipse MAT'i (Memory Analyzer Tool) kullanın — .hprof dosyalarını analiz etmek için ücretsiz bir araç. Dominator tree, path to GC roots, döküm karşılaştırma ve Leak Suspects Report ile otomatik sızıntı tespitini destekler.
Dökümün kendisi — evet, çünkü döküm toplama tüm iş parçacıklarını durdurur (stop-the-world). Döküm olmadan — hayır. Kontrollü ortamlarda (test tezgahı, CI) döküm alın, üretimde değil.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun