0Pricing
Android Academy · Ders

Bellek Sızıntıları ve Çözümleri

Sızıntıları bulun ve durdurun.

Bellek Sızıntıları ve Çözümleri, CoddyKit'te ücretsiz bir Android Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Android Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Android Academy kursu toplamda 4 dersten oluşur.

Bellek Sızıntısı Nedir

Bellek sızıntısı, artık gerekmeyen nesnelerin bir şey hâlâ onlara başvuru tuttuğu için çöp toplayıcı tarafından toplanamaması durumunda oluşur. Android'de bunun klasik kurbanı, ekranı yok edildikten sonra bellekte kalan bir Activity veya Context nesnesidir.

Sızıntılar zamanla yığınınızı büyütür, daha sık çöp toplamayı tetikler (bu da kullanıcı arayüzünü duraklatıp takılmalara yol açar) ve sonunda uygulamanın OutOfMemoryError ile çökmesine neden olur. Bu ders, sızıntıları nasıl bulup düzelteceğinizi gösterir.

Çöp Toplayıcı Neyi Tutacağına Nasıl Karar Verir

Android'in çöp toplayıcısı, bir çöp toplama kökünden (canlı iş parçacıkları, statik alanlar vb.) erişilebilir olan her nesneyi tutar. Erişilemeyen her şey serbest bırakılır.

Sızıntı, basitçe istenmeyen bir erişilebilirlik yoludur: kısa ömürlü bir nesneye başvuru tutan uzun ömürlü bir nesne. Aşağıdaki saf Kotlin gösterimi, erişilebilirliğin bir nesneyi canlı tutmasını gösterir.

object GlobalCache {
    val items = mutableListOf<ByteArray>()
}

fun cacheSomething() {
    // This 1MB array stays alive forever because GlobalCache
    // (a static singleton, a GC root) keeps referencing it.
    GlobalCache.items.add(ByteArray(1_000_000))
}

fun main() {
    repeat(3) { cacheSomething() }
    println("Held arrays: ${GlobalCache.items.size}") // never freed
}

Klasik Örnek: Bir Etkinliğin Sızdırılması

Android'de en yaygın bellek sızıntısı, bir Context'i tutan statik veya uzun ömürlü bir nesnedir. Etkinlik yok edildiğinde (döndürme, gezinme) sistem onu serbest bırakmak ister; ancak statik başvuru onu sonsuza kadar canlı tutar.

Aşağıdaki kod sızıntıya neden olur: tekil nesne, bir etkinlik bağlamını önbelleğe alır.

// LEAK: static field holds an Activity Context
object Analytics {
    var context: Context? = null   // <- keeps Activity alive
    fun init(ctx: Context) { context = ctx }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Analytics.init(this) // passing the Activity -> leak on rotation
    }
}

Çözüm: Uygulama Bağlamını Kullanma

Uzun ömürlü bir nesnede Context saklamanız gerektiğinde, tüm süreç boyunca yaşayan ve güvenle tutulabilen uygulama bağlamını saklayın.

Bir Etkinlik/Görünüm bağlamını yalnızca o ekran var olduğu sürece tutun. Bu tek kural, Android'deki bellek sızıntılarının çoğunu önler.

object Analytics {
    private var appContext: Context? = null
    fun init(ctx: Context) {
        // applicationContext is process-scoped and safe to keep
        appContext = ctx.applicationContext
    }
}

// Call site is now leak-free:
Analytics.init(this) // stores applicationContext, not the Activity

İç Sınıflar ve İşleyiciler

Statik olmayan bir iç sınıf (çoğu dinleyici, Runnable ve Handler geri çağrısı dâhil), dış sınıfına örtük bir başvuru tutar. Bu iş ekranın ömrünü aşarsa ekran sızdırılır.

Gecikmeli bir Handler.postDelayed sık rastlanan bir nedendir: bekleyen ileti, çalışana kadar Etkinliği canlı tutar.

// LEAK: the posted Runnable holds the Activity for 60 seconds
handler.postDelayed({ updateUi() }, 60_000)

// FIX: cancel pending work when the screen goes away
override fun onDestroy() {
    super.onDestroy()
    handler.removeCallbacksAndMessages(null)
}

Eş Yordamlar: İşinizi Bir Kapsama Bağlayın

Ekranını aşan bir eş yordam, yakaladığı her şeyi sızdırır. Çözüm, yapılandırılmış eşzamanlılıktır: işi bir yaşam döngüsüne bağlı bir kapsamda başlatın; böylece iş otomatik olarak iptal edilir.

Bir ViewModel içinde viewModelScope, bir kullanıcı arayüzü denetleyicisinde lifecycleScope kullanın. Sahip yok edildiğinde kapsam iptal edilir ve başvurular serbest bırakılır.

class FeedViewModel : ViewModel() {
    fun load() {
        // Cancelled automatically when the ViewModel is cleared
        viewModelScope.launch {
            val feed = repository.fetchFeed()
            _state.value = feed
        }
    }
}

// In Compose, collect tied to the lifecycle:
val state by viewModel.state.collectAsStateWithLifecycle()

Compose'ta DisposableEffect

Compose'ta kaydettiğiniz her şeyi, bileşen oluşturulabilir yapıdan ayrıldığında kayıttan çıkarmanız gerekir. DisposableEffect, tam olarak bunun için bir onDispose bloğu sağlar: dinleyiciler, gözlemciler, algılayıcılar ve yayın alıcıları.

Buradaki temizleme işlemini unutmak, geri çağrıyı ve onun yakaladığı her şeyi sızdırır.

@Composable
fun LocationDisplay(manager: LocationManager) {
    DisposableEffect(manager) {
        val listener = LocationListener { /* update */ }
        manager.register(listener)
        onDispose { manager.unregister(listener) } // prevents the leak
    }
}

LeakCanary ile Sızıntıları Bulma

LeakCanary, hata ayıklama derlemelerinde sızıntıları otomatik olarak yakalamak için kullanılan standart araçtır. Bağımlılığı eklediğinizde yok edilmiş nesneleri izler; bir nesne çöp toplayıcı tarafından toplanmazsa yığın dökümünü alır ve onu canlı tutan tam referans zincirini gösterir.

Bu zincir, düzeltmenin nerede olduğunu gösterir: soruna neden olan alana veya dinleyiciye doğrudan işaret eder.

// build.gradle.kts (app module)
dependencies {
    debugImplementation("com.squareup.leakcanary:leakcanary-android:2.14")
}
// No code needed: on a debug build, navigate away from a screen and
// LeakCanary posts a notification with the leak trace, e.g.:
//   Analytics.context -> MainActivity (leaked)

Profiler'da Yığın Dökümleri

LeakCanary'nin işaretlemediği sızıntılar (yavaş büyüme, yerel bellek kullanımı, büyük önbellekler) için Bellek Profiler'ını kullanın. Bir yığın dökümü alın, çöp toplamayı zorlayın ve hangi sınıfların şaşırtıcı derecede çok örneğe sahip olduğunu inceleyin.

Başka bir ekrana geçtikten sonra Etkinlik, Parça veya ViewModel örneklerinin sayısının artması, sorunun kesin bir göstergesidir. Profiler ayrıca çöp toplama köklerine giden yolu gösterir; böylece başvuruyu izleyebilirsiniz.

Bitmap'ler ve Büyük Ayırmalar

Her bellek sorunu bir referans sızıntısı değildir. Büyük bitmap'ler ve sınırlandırılmamış önbellekler, tek başlarına yığını doldurabilir. Tam çözünürlüklü bir fotoğraf bellekte onlarca megabayt yer kaplayabilir.

Bir görüntü kitaplığının (Coil/Glide) görüntüyü gösterilen boyuta küçültmesini sağlayın ve oluşturduğunuz tüm önbellekleri açık bir üst sınırla sınırlandırın. Kod parçasında boyutla sınırlandırılmış bir LRU önbelleği gösterilmektedir.

// Bound memory: keep at most ~1/8 of available app memory
val maxKb = (Runtime.getRuntime().maxMemory() / 1024 / 8).toInt()
val bitmapCache = object : LruCache<String, Bitmap>(maxKb) {
    override fun sizeOf(key: String, value: Bitmap) = value.byteCount / 1024
}
// An unbounded HashMap<String, Bitmap> would grow until OutOfMemoryError.

Sızıntı Önleme Kontrol Listesi

Bu alışkanlıkları edinin; böylece çoğu sızıntı hiç oluşmaz:

  • Uzun ömürlü nesnelerde bir Etkinlik/Görünüm yerine applicationContext saklayın.
  • Eşzamansız işleri yaşam döngüsü kapsamına bağlı bir eş yordamda (viewModelScope, lifecycleScope) çalıştırın.
  • Dinleyicilerin/alıcıların kaydını her zaman kaldırın (onDispose, onDestroy).
  • Gecikmeli işleyicileri ve zamanlayıcıları iptal edin.
  • Önbellekleri sınırlandırın ve bitmap'leri küçültün.
  • Hata ayıklama derlemelerinde LeakCanary'yi tutun ve izlerine göre işlem yapın.

Kısa Kontrol

Bir tekil nesnenin, yaşam süresi boyunca kullanmak üzere bir Context tutması gerekiyor. Bir ekranın sızmasını önlemek için hangi bağlamı tutmalıdır?

Özet: Belleği Temiz Tutma

Sızıntıların ne olduğunu ve onları nasıl durduracağınızı öğrendiniz:

  • Sızıntılar, ölü nesneleri canlı tutan istenmeyen erişilebilirlik yollarıdır.
  • Klasik sızıntı, bir Activity/Context'e yapılan statik/uzun ömürlü başvurudur; bunun yerine applicationContext saklayın.
  • İç sınıf dinleyicileri, gecikmeli işleyiciler ve kapsama bağlanmamış eş yordamlar sahiplerini sızdırır; bunları bir kapsama bağlayıp iptal edin.
  • Geri çağrıların kaydını kaldırmak için Compose'ta DisposableEffect kullanın.
  • LeakCanary ve Bellek Profiler'ı referans zincirini ortaya çıkarır.
  • Önbellekleri sınırlandırın ve bitmap'leri küçültün.

Sırada: başlangıç optimizasyonu ve temel profillerle uygulamanın hızlı başlatılmasını sağlamak var.

Sıkça Sorulan Sorular

“Bellek Sızıntıları ve Çözümleri” dersi ücretsiz mi?

Evet — “Bellek Sızıntıları ve Çözümleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Android Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Android Academy kursu toplamda 4 dersten oluşur.

“Bellek Sızıntıları ve Çözümleri” dersinde ne öğreneceğim?

Sızıntıları bulun ve durdurun. Android Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Android Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Android Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Bellek Sızıntıları ve Çözümleri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Android Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Android Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Performansı Ölçme
  2. Yeniden Oluşturmayı Denetleme
  3. Bellek Sızıntıları ve Çözümleri
  4. Başlangıç ve Temel Profiller
← Android Academy Sayfasına Dön