Uygulama Geliştirmede OutOfMemoryError: nedir, nedenleri ve önleme yöntemleri

Yazar: IT Sectr Yayınlanma: 2026-03-29 Okuma süresi: 9 dk

OutOfMemoryError, Java Sanal Makinesi (JVM) veya Android Runtime (ART) yığında (Heap) yeterli alan olmaması nedeniyle yeni bir nesne için bellek ayıramadığında oluşan ölümcül bir istisnadır. Square Engineering'e göre, mobil uygulamalardaki OutOfMemoryError'ların %70'i gerçek sınır aşımından değil, bellek sızıntılarından kaynaklanır. OOM'un nedenlerini anlamak, uygulama kararlılığının anahtarıdır.

Anahtar Noktalar

  • OutOfMemoryError — yeni bir nesne oluşturmak için Heap yetersiz olduğunda bir istisna
  • Heap — tüm Java/Kotlin nesnelerinin bulunduğu bellek alanı
  • Bitmap — Android'de Heap'in ana tüketicisi, tipik bir OOM kaynağı
  • Heap Dump — kimin ne kadar bellek kullandığını analiz etmek için Heap'in anlık görüntüsü
  • OOM tedavisi sızıntıları düzeltmeyi ve bellek tüketimini optimize etmeyi gerektirir

OutOfMemoryError Nedir

OutOfMemoryError (OOM), Java/Kotlin'de VirtualMachineError ailesinden, yeni bir nesne için bellek ayıramama durumunu bildiren bir istisnadır. Kontrol edilen istisnaların aksine, OOM bir Error'dür ve catch ile işlenmesi gerekmez — ancak teknik olarak yakalanabilir. OOM oluştuktan sonra, uygulama genellikle kararsız bir durumdadır ve sonlandırılması önerilir.

Android'de, her uygulamanın cihaz üreticisi tarafından belirlenen bir Heap sınırı vardır. 6+ GB RAM'e sahip modern akıllı telefonlar için sınır 256–512 MB, bütçe cihazları için 128–192 MB'dir. Tüm canlı nesnelerin toplam hacmi bu sınırı aştığında, ART OutOfMemoryError fırlatır.

Anlamak önemlidir: OOM her zaman cihazın fiziksel belleğinin tükendiği anlamına gelmez. Uygulamanın sistem tarafından belirlenen Heap sınırını tükettiği anlamına gelir. Diğer uygulamalar boş belleğe sahip olabilir, ancak Android'deki süreç izolasyonu nedeniyle uygulamanız bunu kullanamaz.

OutOfMemoryError'un Ana Nedenleri

Beş senaryo düzenli olarak mobil uygulamalarda OOM'a yol açar. Her senaryo belirli bir veri türü veya işlemle ilişkilidir.

Ölçeklendirilmemiş Bitmap

Bitmap, Android uygulamalarındaki ana bellek tüketicisidir. FullHD görüntüyü (1920 × 1080) orijinal boyutta yüklemek, ARGB_8888 formatında 8,3 MB yer kaplar. Bir RecyclerView'da bu tür 50 görüntü varsa, bu 415 MB'dir ve herhangi bir cihazın Heap'ini aşar. inSampleSize olmadan görüntü yüklemek, zayıf cihazlarda garantili OOM'dur.

Otomatik ölçeklendirme için Glide veya Coil kullanın. Bu kütüphaneler, görüntüleri orijinal çözünürlük yerine View'a uygun boyutta yükler. BitmapFactory.Options'ın doğrudan kullanımı için inSampleSize uygulayın: bunu ikinin katı olarak hesaplayın, böylece nihai boyut 2048 × 2048 pikseli aşmaz. Ayrıca, şeffaflığı olmayan görüntüler için ARGB_8888 yerine RGB_565 kullanın — bu, bellek tüketimini yarıya indirir.

kotlin
fun loadScaledBitmap(path: String, reqWidth: Int): Bitmap? {
    val opts = BitmapFactory.Options().apply {
        inJustDecodeBounds = true
    }
    BitmapFactory.decodeFile(path, opts)
    opts.inSampleSize = calculateSampleSize(opts.outWidth, reqWidth)
    opts.inJustDecodeBounds = false
    return BitmapFactory.decodeFile(path, opts)
}

Bellek Sızıntıları (Birikim)

Tek bir birkaç KB'lık sızıntı OOM'a neden olmaz. Ancak her ekranda düzinelerce sızıntı birikir: her ekran geçişi bir sızıntı ekler, GC nesneleri serbest bırakamaz ve Heap dolar. Tipik bir desen: kullanıcı profil ekranını 20 kez açar ve kapatır → Heap 200 MB büyür → uygulama OOM ile çöker.

Otomatik sızıntı tespiti için projeye LeakCanary kurun. Tam yığın izi ile sızdırılan her nesneyi gösterecektir. Tüm sızıntılar düzeltildikten sonra Heap tüketimi sabit hale gelir: bir ekran kapatıldıktan sonra bellek temel seviyeye döner.

Bellekte Büyük Dosyalar

Tüm dosyaları byte[] içine yüklemek OOM'a giden doğrudan bir yoldur. 50 MB'lık bir JSON dosyası, ayrıştırma sırasında aynı boyutta bir dize artı bir DOM modeli oluşturacaktır. Belleğe yüklenen video dosyaları, ses tamponları ve büyük protobuf veri kümeleri — tümü tek bir işlemde Heap sınırını aşabilir.

Büyük verileri akışlar kullanarak işleyin: 4–8 KB arabellekli InputStream, akışlı JSON ayrıştırıcı (Jackson veya JsonReader ile Gson), video için MediaCodec. Kullanılabilir Heap'in %10'undan büyük dosyalarda asla File.readBytes() çağırmayın.

Döngüde Çok Sayıda Nesne Oluşturma

Bir döngüde arada GC olmadan yoğun nesne oluşturma, özellikle küçük Heap'li cihazlarda OOM'a yol açabilir. Örnek: GC'nin toplayamadığı 100.000 nesneyi for-döngüsünde oluşturmak. Bu, oyunlarda ve grafik düzenleyicilerde daha yaygındır.

Toplu olarak oluşturulup yok edilen nesneler için Object Pool kullanın. Sayısal veriler için ilkel türler kullanın (List<Float> yerine FloatArray). ViewHolder Pool ile RecyclerView, UI bileşenleri için bu sorunu çözer.

Heap Parçalanması

Parçalanma, toplamda yeterli boş bellek olmasına rağmen yeni bir nesne için bitişik blok bulunmaması durumudur. ART, GC sırasında Heap'i sıkıştırır, ancak her zaman başarılı olmaz. Büyük diziler (Bitmap, byte[]) parçalanmaya karşı en hassas olanlardır.

Android 8+'da ART, genç ve yaşlı nesneleri ayırarak parçalanmayı azaltan Nesil GC kullanır. Yine de, aynı havuzda farklı boyutlarda parçalar ayırmaktan kaçının — önceden ayrılmış sabit boyutlu arabellekler kullanmaya çalışın.

Android'de Heap Sınırları

Android'de Heap sınırı bir sabit değildir — üreticiye, cihaz modeline ve işletim sistemi sürümüne bağlıdır. Google, Uyumluluk Tanım Belgesi (CDD) aracılığıyla minimum gereksinimleri belirler, ancak üreticiler gerçek değerleri belirler.

Cihaz KategorisiTipik HeaplargeHeap
Bütçe (1–2 GB RAM)128–192 MB256–384 MB
Orta Sınıf (3–4 GB RAM)256–384 MB512 MB
Amiral Gemisi (6+ GB RAM)384–512 MB768 MB–1 GB
Tabletler (4+ GB RAM)256–512 MB768 MB
Wear OS32–64 MBYok

Bildirimde android:largeHeap="true" aracılığıyla artırılmış bir sınır talep edebilirsiniz. Dikkatli kullanın: Heap'i artırmak sızıntı sorununu çözmez ve sistem sizin uygulamanız için bellek boşaltmak amacıyla diğer uygulamaları öldürmek zorunda kalırsa kullanıcı deneyimini kötüleştirebilir. Wear OS için Heap sınırı minimumdur — yalnızca 32–64 MB, largeHeap burada kullanılamaz ve bellek tasarrufu iki kat önemlidir.

OutOfMemoryError Teşhisi

OOM teşhisi, bir Heap Dump analizini ve hangi nesnelerin bellek tükettiğini anlamayı gerektirir. Android Studio gerekli tüm araçları sağlar.

Adım 1: OOM anını yakalayın. Android Memory Profiler'da Record memory allocations'a tıklayın ve çökmeye neden olan senaryoyu çalıştırın. Profiler, OOM'dan önce bellek ayırmalarında bir artış gösterecektir. OOM tekrarlanabilir değilse, hata ayıklama yapısında android:smallHeap ile Heap'i azaltın veya manuel GC çağrısıyla DDMS kullanın.

Adım 2: En yoğun yükte (OOM'dan önce) bir Heap Dump alın. Android Studio'da Dump'ı açın: Classes sekmesi Retained Size'a göre sıralanmıştır. En büyük nesneler Bitmap, byte[], String'dir. Her Bitmap için boyutu (genişlik × yükseklik × 4 bayt) ve Stack Trace aracılığıyla yükleme yolunu kontrol edin.

Adım 3: Yinelenen nesnelerin sayısını analiz edin. 200 özdeş Fragment veya Activity görüyorsanız — bu bir sızıntıdır. Aynı boyutta 500 Bitmap varsa — bu bir görüntü önbellekleme sorunudur. MAT (Memory Analyzer Tool), Heap'in %80'ini hangi nesnelerin tuttuğunu gösteren bir Dominator Tree ile daha derin analiz sağlar.

text
// adb aracılığıyla Heap Dump komutu
adb shell am dumpheap com.example.app /data/local/tmp/dump.hprof
adb pull /data/local/tmp/dump.hprof.

OOM Önleme Stratejileri

Kapsamlı bir OOM önleme stratejisi, beş koruma seviyesi içerir: mimari kararlardan üretim izlemesine kadar.

Mimari Kararlar

ViewModel + Repository deseni, verileri UI'dan ayırır ve ekran döndürmede View'in tutulmasını önler. ViewModel, Activity'den daha uzun yaşar, verileri kaybolmaz ve View, bellekte verileri çoğaltmadan yeniden oluşturulabilir. Açık durum yönetimi için LiveData yerine StateFlow kullanın.

Bitmap ve Görüntü Yönetimi

Glide, görüntülerle çalışmak için zorunlu bir kütüphanedir. Otomatik olarak ölçekler, önbelleğe alır (disk + bellek) ve Bitmap'i geri dönüştürür. Büyük listeler için diskCacheStrategy ve skipMemoryCache'i yapılandırın. Animasyonlu görüntüler için Glide'ı GIF/WebP ile kullanın — Bitmap dizisinden daha az bellek kaplarlar.

Üretim İzleme

Firebase Performance Monitoring, bellek tüketimini gerçek zamanlı olarak izler. Heap kullanımı sınırın %80'ini aştığında bir uyarı ayarlayın — bu bir inceleme sinyalidir. Crashlytics, OOM'u bir istisna olarak toplar ve çökmeden önceki son bilinen Heap durumunu gösterir. Android 11+ için, OOM sonlanmalarını tespit etmek üzere ApplicationExitInfo kullanın.

Zayıf Cihazlarda Test

Uygulamayı minimum Heap'li (128–192 MB) cihazlarda test ettiğinizden emin olun. Küçük ekranlı ve küçük Heap'li bir emülatör, bütçe cihazını simüle eder. Uygulama böyle bir cihazda çalışıyorsa, amiral gemilerinde OOM sorunu olmayacaktır. Farklı fiyat kategorilerindeki gerçek cihazlarla Firebase Test Lab kullanın.

kotlin
// Ağır işlem öncesi kullanılabilir Heap kontrolü
fun canAllocate(requiredBytes: Long): Boolean {
    val runtime = Runtime.getRuntime()
    val free = runtime.freeMemory()
    return free > requiredBytes * 2 // %50 tampon
}

Sıkça Sorulan Sorular

OutOfMemoryError try-catch ile yakalanabilir mi?

Teknik olarak evet, ancak önerilmez. OOM'dan sonra uygulama kararsız bir durumdadır: yeni ayırmalar başarısız olabilir ve bazı nesneler kısmen oluşturulmuş olabilir. Catch'teki tek makul eylem, günlüğe kaydetme ve Activity'yi yeniden başlatmadır.

OOM neden tüm cihazlarda oluşmaz?

Heap sınırı cihazlar arasında farklılık gösterir. 300 MB gerektiren bir işlem, 192 MB sınırı olan bir cihazda çöker ancak 512 MB ile amiral gemisinde başarılı olur. OOM senaryolarını tespit etmek için minimum özelliklere sahip cihazlarda test yapın.

largeHeap performansı nasıl etkiler?

largeHeap sınırı artırır ancak uygulamayı hızlandırmaz. GC duraklamaları uzar çünkü büyük bir Heap'i toplamak daha fazla zaman alır. Sistem, bellek sağlamak için arka plan uygulamalarını öldürebilir. largeHeap'i yalnızca nesnel olarak çok fazla belleğe ihtiyaç duyan uygulamalar için kullanın (kameralar, düzenleyiciler).

OOM, sistem öldürmesinden nasıl farklıdır?

OOM, Heap yetersiz olduğunda uygulama içindeki bir istisnadır. Sistem öldürmesi (Low Memory Killer), diğer uygulamalar için bellek boşaltmak amacıyla bir işlemi öldürmek için Linux çekirdeğinin kararıdır. Sistem öldürmesinde, uygulama bir istisna almaz — işlem basitçe sona erer.

Bir Bitmap gerçekte ne kadar bellek tüketir?

Formül: genişlik × yükseklik × bytesPerPixel. ARGB_8888 = 4 B/piksel, RGB_565 = 2 B/piksel. ARGB_8888'de bir FullHD Bitmap (1920 × 1080) = 8,3 MB. 4K Bitmap (3840 × 2160) = 33 MB. Görüntüleri her zaman ekranda görüntüleme için gerekli boyuta ölçeklendirin.

Özet

  • OutOfMemoryError — uygulamanın Heap sınırı tükendiğinde ölümcül bir istisna
  • Ölçeklendirilmemiş Bitmap — mobil uygulamalarda OOM'un ana suçlusu
  • Bellek sızıntıları her geçişte nesne birikimi yoluyla OOM'ların %70'ine neden olur
  • Heap sınırı bütçe cihazlarda 128 MB'tan amiral gemilerinde 512 MB'a kadar değişir
  • Heap Dump ve Retained Size analizi — OOM teşhisi için ana araç
  • Glide veya Coil, her boyuttaki görüntüyle çalışmak için zorunludur
  • Minimum Heap'li cihazlarda test tüm projeler için olmazsa olmazdır

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.

Projeyi tartış

Ayrıca okuyun