Bellek yönetimine genel bakış

Android Runtime (ART) ve Dalvik sanal makinesi, belleği yönetmek için sayfalama ve bellek eşleme (çalıştırma) özelliğini kullanır. Yani, bir uygulamanın değiştirdiği tüm bellek (yeni nesneler tahsis ederek veya eşlenmiş sayfalara dokunarak) RAM'de kalır ve diske ayrılamaz. Bir uygulamanın belleğini serbest bırakmanın tek yolu, uygulamanın barındırdığı nesne referanslarını serbest bırakarak belleği çöp toplayıcının kullanımına sunmaktır. Bu durumun bir istisnası vardır: Değişiklik yapılmadan eklenen dosyalar (ör. kod) için, sistem bu belleği başka bir yerde kullanmak isterse RAM'den çıkarılabilir.

Bu sayfada, Android'in uygulama işlemlerini ve bellek ayırmayı nasıl yönettiği açıklanmaktadır. Uygulamanızda belleği nasıl daha verimli bir şekilde yöneteceğiniz hakkında daha fazla bilgi için Uygulamanızın Belleğini Yönetme bölümüne bakın.

Atık toplama

ART veya Dalvik sanal makinesi gibi yönetilen bir bellek ortamı, ayrılan her bir bellek alanının kaydını tutar. Bir bellek parçasının artık program tarafından kullanılmadığını belirlediğinde, programcının herhangi bir müdahalesi olmadan bu bellek parçasını tekrar yığına serbest bırakır. Yönetilen bellek ortamında kullanılmayan belleği geri kazanmak için kullanılan mekanizma atık toplama olarak bilinir. Atık toplama işleminin iki amacı vardır: Bir programda gelecekte erişilemeyecek veri nesnelerini bulmak ve bu nesneler tarafından kullanılan kaynakları geri kazanmak.

Android'in bellek yığını, nesli kapsayan bir sistemdir. Yani, ayrılan bir nesnenin beklenen ömrü ve boyutuna bağlı olarak, Android'in izlediği farklı ayırma paketleri vardır. Örneğin, yakın zamanda tahsis edilen nesneler Genç nesil kategorisine aittir. Bir nesne yeterince uzun süre aktif kaldığında eski bir nesle yükseltilebilir ve ardından kalıcı bir nesile geçirilebilir.

Her yığın oluşumunun, buradaki nesnelerin kaplayabileceği bellek miktarı için kendi üst sınırı vardır. Bir nesil dolmaya başladığında, sistem bellekte yer açmak için bir atık toplama etkinliği yürütür. Atık toplama süresi, hangi nesil nesne topladığına ve her nesilde kaç etkin nesne bulunduğuna bağlıdır.

Çöp toplama işlemi oldukça hızlı olabilse de uygulamanızın performansını etkileyebilir. Genellikle, ne zaman çöp toplama etkinliğinin gerçekleşeceğini kodunuzun içinden kontrol edemezsiniz. Atık toplama işleminin ne zaman gerçekleştirileceğini belirlemek için sistemde bir dizi ölçüt çalışır. Ölçütler karşılandığında sistem, süreci yürütmeyi bırakır ve atık toplamaya başlar. Animasyon gibi yoğun bir işleme döngüsünün ortasında veya müzik çalarken çöplerin toplanması, işleme süresini uzatabilir. Bu artış, verimli ve sorunsuz kare oluşturma için uygulamanızda kod yürütmenin önerilen 16 ms eşiğini aşmasına neden olabilir.

Ayrıca kod akışınız, atık toplama etkinliklerini daha sık gerçekleşmeye zorlayan veya normalden daha uzun süren işler yürütebilir. Örneğin, bir alfa karıştırma animasyonunun her karesi sırasında bir for döngüsünün en iç kısmına birden fazla nesne ayırırsanız bellek yığınınızı çok sayıda nesneyle kirletebilirsiniz. Bu durumda çöp toplayıcı, birden fazla çöp toplama etkinliği gerçekleştirir ve uygulamanızın performansını düşürebilir.

Atık toplama hakkında daha fazla genel bilgi için Atık toplama bölümünü inceleyin.

Anı paylaşın

Android, ihtiyacı olan her şeyi RAM'e sığdırmak için işlemler genelinde RAM sayfalarını paylaşmaya çalışır. Bunu aşağıdaki şekillerde yapabilir:

  • Her uygulama süreci, Zygote adlı mevcut bir süreçten çatallanır. Zygote işlemi, sistem önyüklenip ortak çerçeve kodu ve kaynakları (etkinlik temaları gibi) yüklediğinde başlar. Yeni bir uygulama işlemi başlatmak için sistem, Zygote işlemini çatallar ve ardından yeni işlemde uygulamanın kodunu yükleyip çalıştırır. Bu yaklaşım, çerçeve kodu ve kaynakları için ayrılan RAM sayfalarının çoğunun tüm uygulama işlemlerinde paylaşılmasını sağlar.
  • Çoğu statik veri bir işleme hapsedilir. Bu teknik, verilerin süreçler arasında paylaşılmasını sağlar ve gerektiğinde sayfa kullanımına olanak tanır. Statik verilere örnek olarak şunlar verilebilir: Dalvik kodu (doğrudan eşleşme için önceden bağlanmış bir .odex dosyasına yerleştirdiğinizde), uygulama kaynakları (kaynak tablosunu, APK'nın zip girişlerini hizalayarak ve APK'nın zip girişlerini uyumlu olacak şekilde tasarlayarak) ve .so dosyalarındaki yerel kod gibi geleneksel proje öğeleri.
  • Android, birçok yerde açıkça tahsis edilmiş paylaşılan bellek bölgelerini (ashmem veya gralloc ile) kullanarak işlemler arasında aynı dinamik RAM'i paylaşır. Örneğin, pencere yüzeyleri uygulama ile ekran birleştirici arasında paylaşılan belleği, imleç arabellekleri ise içerik sağlayıcı ile istemci arasında paylaşılan belleği kullanır.

Paylaşılan belleğin yoğun olarak kullanılması nedeniyle, uygulamanızın ne kadar bellek kullandığını belirlemek dikkatli olmak gerektirir. Uygulamanızın bellek kullanımını doğru şekilde belirlemeye yönelik teknikler RAM kullanımınızı İnceleme bölümünde ele alınmıştır.

Uygulama belleği ayırma ve geri alma

Dalvik yığını, her uygulama işlemi için tek bir sanal bellek aralığıyla sınırlıdır. Bu, mantıksal yığın boyutunu tanımlar. İhtiyaç duyulduğunda büyüyebilecek ancak sistemin her uygulama için tanımladığı sınıra kadar büyüyebilir.

Yığının mantıksal boyutu, yığın tarafından kullanılan fiziksel bellek miktarıyla aynı değildir. Android, uygulamanızın yığınını incelerken Orantılı Küme Boyutu (PSS) adlı bir değeri hesaplar. Bu değer, diğer işlemlerle paylaşılan kirli ve temiz sayfaları hesaba katar ancak bu, yalnızca söz konusu RAM'i paylaşan uygulamaların sayısıyla orantılı bir miktarda hesaplanır. Bu (PSS) toplamı, sistemin fiziksel bellek ayak iziniz olarak kabul ettiği toplam alanı ifade eder. PSS hakkında daha fazla bilgi edinmek için RAM kullanımınızı İnceleme kılavuzunu inceleyin.

Dalvik yığını, yığının mantıksal boyutunu küçültmez. Diğer bir deyişle Android, alanı kapatmak için yığını birleştirmez. Android, yalnızca yığının sonunda kullanılmayan alan olduğunda mantıksal yığın boyutunu küçültebilir. Ancak sistem, yığın tarafından kullanılan fiziksel belleği azaltmaya devam edebilir. Atık toplama işlemi sonrasında Dalvik, yığını gezerek kullanılmayan sayfaları bulur ve daha sonra madvise kullanarak bu sayfaları çekirdeğe geri döndürür. Bu nedenle, büyük parçaların eşlenmiş ayırmaları ve ayırmaları, kullanılan fiziksel belleğin tamamının (veya neredeyse tamamının) geri çekilmesiyle sonuçlanır. Bununla birlikte, küçük bir ayırma için kullanılan sayfa hâlâ serbest bırakılmamış başka bir şeyle paylaşılabilir. Bu nedenle, küçük ayırmalarda belleğin geri kazanılması çok daha az verimli olabilir.

Uygulama belleğini kısıtla

Android, işlevsel bir çoklu görev ortamını korumak için her uygulamanın yığın boyutuna sabit bir sınır belirler. Kesin yığın boyutu sınırı, cihazın toplam kullanılabilir RAM miktarına bağlı olarak cihazlar arasında değişiklik gösterir. Uygulamanız yığın kapasitesine ulaştıysa ve daha fazla bellek ayırmaya çalışırsa OutOfMemoryError alabilir.

Bazı durumlarda, örneğin bir önbellekte ne kadar veri saklanmanın güvenli olduğunu belirlemek için, geçerli cihazda tam olarak ne kadar yığın alanınızın bulunduğunu belirlemek üzere sistemi sorgulamak isteyebilirsiniz. getMemoryClass() yöntemini çağırarak sistemi bu sayı için sorgulayabilirsiniz. Bu yöntem, uygulamanızın yığını için kullanılabilir megabayt sayısını belirten bir tam sayı döndürür.

Uygulamalar arasında geçiş yapma

Kullanıcılar uygulamalar arasında geçiş yaptığında Android, ön planda olmayan, yani kullanıcı tarafından görülmeyen veya müzik çalma gibi bir ön plan hizmeti çalıştıran uygulamaları önbellekte tutar. Örneğin, kullanıcı bir uygulamayı ilk kez başlattığında uygulama için bir süreç oluşturulur, ancak kullanıcı uygulamadan ayrıldığında bu işlemden çıkılmaz. Sistem, işlemi önbelleğe alır. Kullanıcı daha sonra uygulamaya dönerse sistem, süreci yeniden kullanarak uygulama geçişini hızlandırır.

Uygulamanızda, önbelleğe alınmış bir işlem varsa ve halihazırda ihtiyaç duymadığı kaynakları koruyorsa kullanıcı bu işlemi kullanmıyor olsa bile uygulamanız sistemin genel performansını etkiler. Sistemde bellek gibi kaynaklar azaldığında önbellekteki işlemleri sonlandırır. Sistem, en fazla bellekte kalan işlemleri de hesaba katar ve RAM boşaltmak için bu işlemleri sonlandırabilir.

Not: Uygulamanız önbellekteyken ne kadar az bellek kullanırsa kapatılmama ve hızlı bir şekilde çalışmaya devam etme olasılığı o kadar artar. Ancak anlık sistem gereksinimlerine bağlı olarak, önbelleğe alınan işlemlerin kaynak kullanımları ne olursa olsun herhangi bir zamanda sonlandırılması mümkündür.

Ön planda çalışmadığı sırada işlemlerin nasıl önbelleğe alındığı ve Android'in hangi işlemlerin kapatılabileceğine nasıl karar verdiği hakkında daha fazla bilgiyi İşlemler ve İş Parçacıkları rehberinde bulabilirsiniz.

Bellek stres testi

Bellek stresi sorunları üst segment cihazlarda daha az yaşansa da, Android (Go sürümü) gibi düşük RAM'li cihazlarda kullanıcılar için sorunlara neden olabilir. Uygulama davranışını doğrulamak ve düşük bellekli cihazlardaki kullanıcılarınızın deneyimini iyileştirmek için araç testleri yazabilmek ve bellek stresli olan bu ortamı yeniden oluşturmayı denemek önemlidir.

Stresli Uygulama Testi

Stresli Uygulama Testi (stressapptest), uygulamanız için çeşitli bellek ve donanım sınırlamalarını test etmek amacıyla gerçekçi ve yüksek yük durumları oluşturmaya yardımcı olan bir bellek arayüzü testidir. Zaman ve bellek sınırlamalarını tanımlayabilme özelliği sayesinde, yüksek bellek gerektiren durumlarda gerçek hayatta karşılaşılan durumları doğrulamak için araçlar yazabilirsiniz. Örneğin, veri dosya sisteminizdeki statik kitaplığı aktarmak, çalıştırılabilir hale getirmek ve 990 MB boyutunda 20 saniye süreyle bir stres testi çalıştırmak için aşağıdaki komut dizisini kullanın:
    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

Aracın yüklenmesi, yaygın bağımsız değişkenler ve hata işleme bilgileri hakkında daha fazla bilgi için stressapptest dokümanlarına bakın.

Stres uygulama testi gözlemleri

stressapptest gibi araçlar, serbest kullanılabilir değerden daha yüksek bellek ayırmaları istemek için kullanılabilir. Bu tür bir istek, geliştirme açısından dikkat etmeniz gereken çeşitli uyarılar doğurabilir. Bellek yetersizliği nedeniyle bildirilebilecek üç ana uyarı şunlardır:
  • SIGABRT: Bu, sistem zaten bellek baskısı altındayken boş bellekten daha büyük boyuttaki ayırmaların istenmesi nedeniyle işleminiz için önemli, yerel bir kilitlenmedir.
  • SIGQUIT: Temel bellek dökümü oluşturur ve araç testiniz tarafından algılandığında işlemi sonlandırır.
  • TRIM_MEMORY_EVENTS: Bu geri çağırma işlevleri Android 4.1 (API düzeyi 16) ve sonraki sürümlerde kullanılabilir ve işleminiz için ayrıntılı bellek uyarıları sağlar.