Bu sayfada, uygulamanızdaki bellek kullanımını proaktif olarak nasıl azaltacağınız açıklanmaktadır. Android işletim sisteminin belleği nasıl yönettiği hakkında bilgi edinmek için Bellek yönetimine genel bakış başlıklı makaleyi inceleyin.
Rastgele erişimli bellek (RAM), herhangi bir yazılım geliştirme ortamı için değerli bir kaynaktır. Fiziksel belleğin genellikle sınırlı olduğu mobil işletim sistemlerinde ise daha da değerlidir. Android Çalışma Zamanı (ART) ve Dalvik sanal makinesi rutin atık toplama işlemi gerçekleştirse de bu, uygulamanızın belleği ne zaman ve nerede ayırıp serbest bıraktığını göz ardı edebileceğiniz anlamına gelmez. Yine de genellikle statik üye değişkenlerindeki nesne referanslarını tutmaktan kaynaklanan bellek sızıntılarını önlemeniz ve yaşam döngüsü geri çağırmaları tarafından tanımlanan uygun zamanda Reference nesnelerini serbest bırakmanız gerekir.
Uygulamanızın kod ve kaynak ayak izini azaltma
Kodunuzdaki bazı kaynaklar ve kitaplıklar, farkında olmadan bellek tüketebilir. Uygulamanızın genel boyutu (üçüncü taraf kitaplıkları veya yerleştirilmiş kaynaklar dahil), uygulamanızın ne kadar bellek tükettiğini etkileyebilir. Kodunuzdaki gereksiz, lüzumsuz veya şişirilmiş bileşenleri, kaynakları ve kitaplıkları kaldırarak uygulamanızın bellek tüketimini iyileştirebilirsiniz.
R8'i etkinleştirerek uygulamanın genel boyutunu küçültme
Derlenmiş uygulama kodunuz, çalışma zamanı belleğinizin etkin bir parçasıdır. Her sınıf, yöntem, kitaplık bağımlılığı ve dize sabiti çalıştırıldığında RAM'e yüklenmelidir. Derlenmiş kod tabanınız ne kadar büyükse uygulamanızın var olması için o kadar fazla fiziksel RAM gerekir.
Uygulamanızın bellekte kapladığı yeri azaltmak için R8'i kullanabilirsiniz. R8 geleneksel olarak APK boyutunu küçültmesiyle bilinse de çalışma zamanı belleği (RAM) üzerinde doğrudan ve olumlu bir etkisi vardır. R8, uygulamanızın bayt kodunu analiz ederek kullanılmayan kodları kaldırır, gereksiz sınıfları birleştirir, yöntemleri satır içi yapar ve tanımlayıcıları küçültür. APK'dan RAM'e daha az derlenmiş bayt kod yükleyerek uygulamanın genel taban bellekte kaplanan yerini azaltır. Ayrıca, sınıf, yöntem ve alan adlarının kısaltılmış tanımlayıcılara küçültülmesi, RAM yükünü doğrudan azaltır. Sınıf birleştirme ve kapsamlı yöntem satır içi ekleme gibi optimizasyonlar, maliyetli çalışma zamanı aramalarının ve ayırma kalıplarının yerini alarak yığın ve yığın belleğin optimize edilmesini sağlar.
Saklama kurallarını anlama
Koruma kuralları, R8'e optimizasyon sırasında kodunuzun hangi bölümlerinin korunacağını söyleyen yapılandırma talimatlarıdır. Bu kurallar, R8'in uygulamanızın kullandığı kodu kaldırmasını veya küçültmesini önler. Daha fazla bilgi için Keep kurallarına genel bakış başlıklı makaleyi inceleyin.
Kötü yazılmış koruma kuralları, R8'in kod tabanınızın büyük bölümlerini optimize etmesini engeller. Çok geniş kapsamlı saklama kurallarından kaçının ve şu en iyi uygulamaları izleyin:
- Kaçınılması gereken genel kurallar:
-dontoptimize: Uygulamanın tamamında optimizasyonu tamamen devre dışı bırakır. Bu da daha büyük ve daha yavaş çalıştırılabilir dosyalarla sonuçlanır.-dontshrink: Kullanılmayan kod ve kaynakların kaldırılmasını önler.-dontobfuscate: Ad küçültmeyi önler ve değerli bellek tasarruflarını (özellikle büyük uygulamalarda) kaçırır.
Paket genelinde joker karakterlerden kaçının:
-keep class com.example.package.** { *; }gibi geniş kapsamlı kurallar, R8'in söz konusu paketteki her sınıfı, alanı ve yöntemi korumasına neden olur. Bu, R8'in söz konusu paketteki kodu kaldırma, optimize etme veya küçültme özelliğini tamamen durdurur.Varsayılan R8 yapılandırma dosyasını kullanın: Her zaman
proguard-android-optimize.txtkullanın.
Saklama kuralları yazma hakkında daha fazla bilgi için Saklama kurallarına genel bakış başlıklı makaleyi inceleyin. Kullanılacak ve kaçınılacak belirli kalıplar için Keep kurallarıyla ilgili en iyi uygulamalar başlıklı makaleyi inceleyin.
R8 Yapılandırma Analiz Aracı, R8 yapılandırmanız ve her saklama kuralının uygulamanızı nasıl etkilediği hakkında analizler sağlar. Optimizasyonu engelleyen kuralları belirleme hakkında daha fazla bilgi için R8 Yapılandırma Analiz Aracı başlıklı makaleyi inceleyin.
Harici kitaplıkları kullanma konusunda dikkatli olun
Harici kitaplık kodu genellikle mobil ortamlar için yazılmaz ve mobil istemcide çalışmak için verimsiz olabilir. Harici bir kitaplık kullandığınızda bu kitaplığı mobil cihazlar için optimize etmeniz gerekebilir. Bu çalışmayı önceden planlayın ve kullanmadan önce kitaplığı kod boyutu ve RAM alanı açısından analiz edin.
Mobil cihazlar için optimize edilmiş bazı kitaplıklar bile farklı uygulamalar nedeniyle sorunlara neden olabilir. Örneğin, bir kitaplık lite protobuf'ları kullanırken diğeri micro protobuf'ları kullanabilir. Bu durumda uygulamanızda iki farklı protobuf uygulaması olur. Bu durum, günlük kaydı, analiz, resim yükleme çerçeveleri, önbelleğe alma ve beklemediğiniz birçok şeyin farklı uygulamalarında yaşanabilir.
R8 kullanarak uygulamanızı optimize etmek, bağımlılıklardan kullanılmayan kodu kaldırabilir ancak bu işlemin etkinliği genellikle kitaplığın dahili yapılandırmasıyla sınırlıdır. Örneğin, geniş kapsamlı saklama kuralları veya bir kitaplıkta yansıtma kullanılması, R8'in kodunu küçültmesini engelleyebilir ve bu da daha büyük bir bellek alanı kaplamasına neden olur. Verimli kitaplıklar seçme stratejileri için Kitaplıkları akıllıca seçme başlıklı makaleyi inceleyin.
Düzinelerce özellikten yalnızca bir veya ikisi için paylaşılan kitaplık kullanmaktan kaçının. Kullanmadığınız çok miktarda kodu ve ek yükü dahil etmeyin. Kitaplık kullanıp kullanmayacağınıza karar verirken ihtiyacınıza en uygun uygulamayı arayın. Aksi takdirde, kendi uygulamanızı oluşturmayı tercih edebilirsiniz.
Bağımlılık ekleme için Hilt veya Dagger 2 kullanma
Bağımlılık ekleme çerçeveleri, yazdığınız kodu basitleştirebilir ve test ile diğer yapılandırma değişiklikleri için yararlı olan uyarlanabilir bir ortam sağlayabilir.
Uygulamanızda bağımlılık ekleme çerçevesi kullanmayı planlıyorsanız Hilt veya Dagger'ı kullanmayı düşünebilirsiniz. Hilt, Dagger üzerinde çalışan Android için bir bağımlılık ekleme kitaplığıdır. Dagger, uygulamanızın kodunu taramak için yansıtma kullanmaz. Android uygulamalarında Dagger'ın statik derleme zamanı uygulamasını gereksiz çalışma zamanı maliyeti veya bellek kullanımı olmadan kullanabilirsiniz.
Yansıtma kullanan diğer bağımlılık ekleme çerçeveleri, kodunuzu ek açıklamalar için tarayarak işlemleri başlatır. Bu işlem, önemli ölçüde daha fazla CPU döngüsü ve RAM gerektirebilir ve uygulama başlatıldığında belirgin bir gecikmeye neden olabilir.
Bağımlılık yerleştirme tekniğini kullanırken nesnelerin kapsamının uygun şekilde belirlendiğinden emin olarak bellek sızıntılarını önlemeye dikkat edin. Nesneleri yanlış yaşam döngüsüne bağlayarak gereğinden uzun süre saklamak bellek sızıntılarına yol açabilir.
Görüntü yükleme konusunda dikkatli olun
Grafik bit eşlemler genellikle uygulamanızın belleğinde bulunan en büyük ortak nesnelerdir. JPEG gibi sıkıştırılmış dosyalarla çalışıyor olsanız bile, dosyanın ekranda gösterilmesi için sıkıştırılmamış bir bit eşleme haline getirilmesi gerekir. Küçük bir sıkıştırılmış resim dosyası çok büyük bir bit eşleme olarak genişleyebilir.
Örneğin, çoğu bit eşlem ARGB_8888 yapılandırmasını kullanır. Bu yapılandırmada her piksel için 4 baytlık bellek gerekir. Kırmızı, yeşil, mavi ve alfa (şeffaflık) için birer bayt ayrılır. 100 KB boyutunda bir JPEG'iniz varsa ve bunu 1.000x1.000 piksellik bir görünümde gösteriyorsanız bit eşlem, 1.000.000 pikselin her biri için 4 bayt gerektirir ve toplamda 4 MB bellek kullanır.
Resim kullanımınızı optimize etmek için yapabileceğiniz birkaç şey vardır. Örneğin, resim yükleme kitaplıklarını kullanmak, ihtiyaç duyulmadığında belleği serbest bırakmanıza yardımcı olabilir. Görüntüleri verimli bir şekilde işleme hakkında bilgi edinmek için Bitmap görüntüleri optimize etme başlıklı makaleyi inceleyin.
Kullanılabilir belleği ve bellek kullanımını izleme
Uygulamanızın bellek kullanımıyla ilgili sorunları düzeltebilmek için önce bu sorunları bulmanız gerekir. Android Studio bellek profil aracı, bellek sorunlarını aşağıdaki şekillerde bulup teşhis etmenize yardımcı olur:
- Uygulamanızın zaman içinde belleği nasıl tahsis ettiğini görün. Bellek profil oluşturucu, uygulamanızın kullandığı bellek miktarı, ayrılan Java nesnelerinin sayısı ve atık toplama işleminin ne zaman gerçekleştiğiyle ilgili gerçek zamanlı bir grafik gösterir.
- Atık toplama etkinliklerini başlatın ve uygulamanız çalışırken Java yığınının anlık görüntüsünü alın.
- Uygulamanızın bellek ayırmalarını kaydedin, ayrılan tüm nesneleri inceleyin, her ayırma için yığın izleme (stack trace) görüntüleyin ve Android Studio düzenleyicisinde ilgili koda gidin.
Bellek profil oluşturucu, LeakCanary bellek sızıntısı tespit kitaplığıyla da entegre olur. LeakCanary'yi kullanarak bellek sızıntısı analizini test cihazından geliştirme makinenize taşıyabilir ve iş akışınızı önemli ölçüde hızlandırabilirsiniz. Daha fazla bilgi için Android Studio sürüm notlarına bakın.
Üretim uygulamanızı çalıştıran kullanıcıların verilerine göre bellek sorunlarını teşhis etmek için kullanabileceğiniz başka araçlar da vardır:
- Düşük bellek nedeniyle işlem sonlandırma (LMK) etkinliklerini izlemek için Android Vitals'ı kullanın.
- Bellek yetersizliği hatalarının yanı sıra bellek sızıntılarından kaynaklanabilecek anormal uygulama davranışlarını izlemek için Profiling Manager'ı kullanın.
Olaylara göre belleği serbest bırakma
Android, Bellek yönetimine genel bakış bölümünde açıklandığı gibi, kritik görevler için bellek boşaltmak gerektiğinde uygulamanızdan bellek geri alabilir veya uygulamanızı tamamen durdurabilir. Sistem belleğini daha da dengelemek ve sistemin uygulama işleminizi durdurmasını önlemek için ComponentCallbacks2 arayüzünü Activity sınıflarınızda uygulayabilirsiniz. Sağlanan onTrimMemory()
geri çağırma yöntemi, uygulamanızı yaşam döngüsü veya bellekle ilgili etkinlikler konusunda bilgilendirir. Bu etkinlikler, uygulamanızın bellek kullanımını gönüllü olarak azaltması için iyi bir fırsat sunar.
Belleği boşaltmak, uygulamanızın bellek azaldığında uygulamaları kapatan işlem tarafından kapatılma sıklığını azaltabilir.
onTrimMemory() uygulamanız yalnızca TRIM_MEMORY_UI_HIDDEN ve TRIM_MEMORY_BACKGROUND etkinliklerine odaklanmalıdır. (Android 14'ten itibaren sistem, diğer eski sabitler için bildirim göndermez. Bu sabitler, Android 15'te resmen kullanımdan kaldırıldı.)
TRIM_MEMORY_UI_HIDDEN: Bu sinyal, uygulamanızın kullanıcı arayüzünün kullanıcının görünümünden çıktığını gösterir. Bu geçiş, bit eşlemler, video oynatma arabellekleri veya karmaşık animasyon kaynakları gibi kesinlikle kullanıcı arayüzüne bağlı olan önemli bellek ayırmalarını serbest bırakma fırsatı sunar.TRIM_MEMORY_BACKGROUND: Bu sinyal, işleminizin arka planda çalıştığını ve sistemin genel bellek ihtiyaçlarını karşılamak için sonlandırılmaya aday olduğunu gösterir. İşleminizin önbelleğe alınmış durumda kalma süresini uzatmak ve uygulamanın soğuk başlatma sayısını azaltmak için, kullanıcı oturumuna devam ettiğinde kolayca yeniden oluşturulabilecek tüm kaynakları agresif bir şekilde serbest bırakmanız gerekir.
Bu kod örneğinde, farklı bellekle ilgili etkinliklere yanıt vermek için onTrimMemory() geri çağırma işlevinin nasıl uygulanacağı gösterilmektedir:
Kotlin
import android.content.ComponentCallbacks2
// Other import statements.
class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
// Other activity code.
/**
* Release memory when the UI becomes hidden or when system resources become low.
* @param level the memory-related event that is raised.
*/
override fun onTrimMemory(level: Int) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
Java
import android.content.ComponentCallbacks2;
// Other import statements.
public class MainActivity extends AppCompatActivity
implements ComponentCallbacks2 {
// Other activity code.
/**
* Release memory when the UI becomes hidden or when system resources become low.
* @param level the memory-related event that is raised.
*/
public void onTrimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
Ne kadar belleğe ihtiyacınız olduğunu kontrol etme
Android, birden fazla işlemin çalışmasına izin vermek için her uygulamaya ayrılan yığın boyutu için kesin bir sınır belirler. Yığın boyutu sınırı, cihazın genel olarak ne kadar RAM'e sahip olduğuna bağlı olarak cihazlar arasında değişiklik gösterir. Uygulamanız yığın kapasitesine ulaşıp daha fazla bellek ayırmaya çalışırsa sistem OutOfMemoryError oluşturur.
Yetersiz bellek sorununu önlemek için sistemi sorgulayarak mevcut cihazda ne kadar yığın alanı olduğunu belirleyebilirsiniz. getMemoryInfo() işlevini çağırarak bu rakam için sistemi sorgulayabilirsiniz. Bu, kullanılabilir bellek, toplam bellek ve sistemin işlemleri durdurmaya başladığı bellek düzeyi olan bellek eşiği de dahil olmak üzere cihazın mevcut bellek durumu hakkında bilgi sağlayan bir ActivityManager.MemoryInfo nesnesi döndürür. ActivityManager.MemoryInfo nesnesi, cihazın belleğinin azalıp azalmadığını belirten basit bir Boole değeri olan lowMemory değerini de gösterir.
Aşağıdaki örnek kod snippet'inde, uygulamanızda getMemoryInfo() yönteminin nasıl kullanılacağı gösterilmektedir.
Kotlin
fun doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check whether the device is in a low memory state.
if (!getAvailableMemory().lowMemory) {
// Do memory intensive work.
}
}
// Get a MemoryInfo object for the device's current memory status.
private fun getAvailableMemory(): ActivityManager.MemoryInfo {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return ActivityManager.MemoryInfo().also { memoryInfo ->
activityManager.getMemoryInfo(memoryInfo)
}
}
Java
public void doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check whether the device is in a low memory state.
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
if (!memoryInfo.lowMemory) {
// Do memory intensive work.
}
}
// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
Düşük bellek nedeniyle sonlandırılan işlemleri izleme
Kullanıcı tarafından algılanan düşük bellek sorunu (LMK), sistem belleği kritik düzeyde azaldığında meydana gelir. Bellek azaldığında lmkd (düşük bellek durumunda işlem sonlandırma arka plan programı), işlemleri oom_adj_score değerlerine göre sonlandırır. Önbelleğe alınan veya ilişkili kullanıcı arayüzü olmayan bir hizmet (ör. iş) çalıştıran uygulamalar en yüksek puanları alır ve ilk olarak sonlandırılır. Bellek kritik düzeyde düşük kalırsa daemon, oom_adj_score değeri 0 olan işlemlerden bellek geri almaya zorlanır.
Bu puan görünür uygulamalar için ayrıldığından, bu uygulamaların sonlandırılması hemen gerçekleşir ve sorunsuz bir şekilde çıkış yapılmaz. Son kullanıcıya göre uygulama çökmüş gibi görünür. Bu durum genellikle standart yaşam döngüsü durumu kaydetme mekanizmalarını atlayarak kullanıcının ilerlemesinin kaybolmasına neden olur.
Android Vitals'da ön plan işlemlerinin sonlandırılmasına öncelik verilir. Bunun nedeni, bu işlemlerin bellek yönetimiyle ilgili sorunlar için yüksek doğrulukta bir proxy görevi görmesidir. %1'den yüksek bir LMK oranı, acil işlem yapılması gerektiğini gösterse de düşük bir oran, hesabın sağlıklı olduğu anlamına gelmez. Kullanıcı tarafından algılanan düşük LMK oranı, LMK arka plan programının arka planda çalışırken işlemleri sık sık sonlandırdığı anlamına gelebilir. Bu durum, "hazır durumda başlatma" performansını ve çoklu görev akıcılığını düşürür. Bu nedenle, uzun vadeli kararlılık ve cihaz sağlığı için mevcut LMK puanınızdan bağımsız olarak bellekle ilgili en iyi uygulamalara uymanızı öneririz.
Bellek sorunlarını izlemek için ProfilingManager öğesini kullanma
Android platformu, ProfilingManager adlı bir gelişmiş gözlemlenebilirlik API'si sunar. Bu API, üretimde kullanıcı verilerini ayarladığınız tetikleyicilere göre yakalamanıza olanak tanır. Bu işlem, yeniden üretilmesi zor olan bellek sorunlarını belirlemenize yardımcı olabilir.
Android 17 ile kullanıma sunulan iki yeni tetikleyici, bellek sorunlarını tespit etmek için özellikle yararlıdır:
TRIGGER_TYPE_OOMUygulamanınOutOfMemoryErroroluşturduğunu gösterir. Uygulama, kilitlenmeden sonraki başlatılışında profil oluşturma tetikleyicileri için kaydolduğunda tetiklenir.TRIGGER_TYPE_ANOMALYsistem, uygulamada anormal davranış algıladığında tetiklenir. Bu durum, diğer nedenlerin yanı sıra aşırı bellek kullanımından da kaynaklanabilir. Bu uyarı, uygulama aşırı bellek kullanımı gösterdikten ve sistem, sorunlu işlemi durdurmak için herhangi bir işlem yapmadan önce tetiklenir. Örneğin, uygulama Android 17'de kullanıma sunulan bellek sınırlarını aşıyorsaTRIGGER_TYPE_ANOMALY, sistem uygulamayı kapatmadan önce tetiklenir.
ProfilingManager kullanarak tetikleyicileri programatik olarak kaydetme ve alma hakkında daha fazla bilgi için tetikleyici tabanlı profilleme belgelerine bakın. Firebase Crashlytics, ayrıca hem TRIGGER_TYPE_OOM hem de TRIGGER_TYPE_ANOMALY tetikleyicilerini destekler ve bunları diğer teşhis meta verileriyle ilişkilendirir.
Ayrıca, izleme başlangıç ve bitiş noktalarını manuel olarak tanımlamak için uygulama odaklı profillemeyi kullanabilirsiniz. Bellek sızıntısı veya aşırı bellek kullanımı olabileceğinden şüphelendiğiniz alanlarda yığın dökümlerini veya yığın profillerini manuel olarak yakalamak için bu işlemi yapmanızı öneririz.
İşlem durumunu ve belleği izleme
Bellek geri çağırmalarına ve etkinliklerine ek olarak, uygulamanızın işlemlerinin durumunu ve önceliğini açıkça sorgulayabilirsiniz. Bu, özellikle işletim sisteminin uygulamanızın mevcut durumunu nasıl sınıflandırdığını (ör. uygulamanızın ön planda mı, kullanıcı tarafından algılanan mı yoksa önbelleğe alınmış mı olduğu) ve düşük bellekli sonlandırıcı tarafından sonlandırılma riski olup olmadığını anlamak için kullanışlıdır.
Sürekli izleme için Python kontrol paneliyle
Uygulamanızın işlemlerini ve bellekte kapladığı yeri sürekli olarak izlemek için uygulamanızı çalıştırırken Android Memory Monitor Python komut dosyasını kullanın. Bu, uygulamanızın işlemlerinin durumunu ve bellek kullanımını anlamanıza yardımcı olmak için terminal ve web kontrol panellerini görüntülemek üzere adb komutlarını kullanan bir komut satırı aracıdır. Kontrol panellerini başlatmak için komut dosyasını uygulamanızın paket adıyla birlikte çalıştırın. Örneğin:
python3 android_mem_monitor.py your.package.name
Kontrol paneli özellikleri ve kullanımıyla ilgili ayrıntılı talimatlar için lütfen README dosyasına veya komut dosyasının satır içi yorumlarına bakın.
Çalışma zamanında ActivityManager ile
Çalışma zamanında çalışan işlemleriniz hakkında bilgi almak için ActivityManager.getRunningAppProcesses() sorgusunu kullanabilirsiniz. Bu işlem, uygulama işlemlerinizin her biriyle ilgili temel bilgileri içeren bir nesne listesi döndürür. importance alanı, sistemin sürece verdiği göreli önemi gösterir ve aşağıdaki gibi sabitlerle eşlenir:
IMPORTANCE_FOREGROUND: İşlem, ön plandaki kullanıcı arayüzünü etkin olarak çalıştırıyor.IMPORTANCE_FOREGROUND_SERVICE: İşlem, kullanıcı tarafından algılanan bir hizmet örneği olan ön plan hizmeti (ör. etkin fon müziği veya büyük indirmeler) çalıştırıyor.IMPORTANCE_CACHED: Bu işlem, önbelleğe alınmış kod içeriyor. İşlem dondurulur ve kullanılmayan belleği Android tarafından geri alınır. Bu durumda işletim sistemi, uygulamaya özgü bellek eşiğini aştığı için uygulamayı sonlandırmaz.MemoryLimiterAncak genel sistemde bellek azaldığında uygulama, düşük bellekli işlemleri sonlandıran program için öncelikli bir aday olur.
adb ile hata ayıklama için
Bellek davranışında ve süreç yaşam döngülerinde hata ayıklarken uygulamanızın OOM puanlarını ve bellek ayak izini gerçek zamanlı olarak incelemenize yardımcı olması için adb komutlarını da kullanabilirsiniz. Uygulamanızın işlemlerini ve bellek durumlarını izlemek için aşağıdaki komutları kullanabilirsiniz:
- Etkin işlem kimliklerini (PID'ler) bulma: Öncelikle, paket adınıza göre filtrelenmiş
pskomutunu kullanarak uygulamanızın şu anda çalıştırdığı tüm işlemleri bulun.
shell adb shell ps -A | grep your.package.name - Mevcut OOM puanını kontrol edin: Bir işlemin PID'sini kullanarak işlem dosya sisteminden OOM puanını okuyun. 0-199 puanı genellikle ön plana çıkarılmış bir uygulamayı, 200-249 puanı algılanabilir bir hizmeti, 250-899 puanı arka plan hizmetini, 900 ve üzeri puanlar ise işlemin önbelleğe alındığını ve sonlandırılma olasılığının yüksek olduğunu gösterir.
shell adb shell cat /proc/pid/oom_score_adj - OOM puanlarını sürekli olarak izleyin: Bir uygulamanın OOM puanındaki (tüm işlemleri arasındaki en düşük OOM puanı) değişiklikleri sürekli olarak izlemek için
watch-uidskomutunu kullanabilirsiniz.
shell adb shell am watch-uids - Bellek ayak izlerini ölçme: Bir işlemin temel bellek ayak izinin (ör. anonim RSS ve takas bellek kullanımı) hızlı bir şekilde okunması için durumunu doğrudan Linux işlem dosya sisteminden okuyun.
shell adb shell cat /proc/pid/status | grep -E "VmRSS|RssAnon|VmSwap"
Bellek ayırmalarının daha ayrıntılı ve kapsamlı bir dökümü içindumpsys meminfokomutunu kullanın:
shell adb shell dumpsys meminfo pid - Etkin bileşenleri inceleme: İşleminiz beklenmedik şekilde yüksek bir önceliği koruyorsa (ör. önbelleğe alınmak yerine
200OOM puanında kalıyorsa) işlemin tam olarak ne çalıştırdığını inceleyebilirsiniz.dumpsys activity processeskomutu, süreci canlı tutan belirli Etkinlikleri, Hizmetleri, Sağlayıcıları ve Alıcıları gösterir.
shell adb shell dumpsys activity processes your.package.name
Daha az bellek kullanan kod yapıları kullanma
Bazı Android özellikleri, Java sınıfları ve kod yapıları diğerlerinden daha fazla bellek kullanır. Kodunuzda daha verimli alternatifler seçerek uygulamanızın kullandığı bellek miktarını en aza indirebilirsiniz.
Hizmetleri dikkatli kullanın
Gereksiz olduğunda hizmetleri çalıştırmamaya özen göstermenizi önemle tavsiye ederiz. Gereksiz hizmetlerin çalışır durumda bırakılması, bir Android uygulamasının yapabileceği en kötü bellek yönetimi hatalarından biridir. Uygulamanızın arka planda çalışması için bir hizmete ihtiyacı varsa bir iş çalıştırması gerekmediği sürece hizmeti çalıştırmaya devam etmeyin. Hizmetinizin görevini tamamladığında durdurulmasını sağlayın. Aksi takdirde bellek sızıntısına neden olabilirsiniz.
Bir hizmeti başlattığınızda sistem, bu hizmetin sürecini çalıştırmaya devam etmeyi tercih eder. Bu davranış, bir hizmet tarafından kullanılan RAM diğer işlemler için kullanılamadığından hizmet işlemlerini çok pahalı hale getirir. Bu durum, sistemin LRU önbelleğinde tutabileceği önbelleğe alınmış işlem sayısını azaltarak uygulama geçişini daha az verimli hale getirir. Belleğin az olduğu ve sistemin şu anda çalışan tüm hizmetleri barındıracak kadar işlem sürdüremediği durumlarda sistemde aşırı bellek kullanımına bile yol açabilir.
Genel olarak, kullanılabilir bellek üzerinde sürekli talepleri olduğundan kalıcı hizmetleri kullanmaktan kaçının. Bunun yerine WorkManager gibi alternatif bir uygulama kullanmanızı öneririz.
Arka plan işlemlerini planlamak için WorkManager simgesinin nasıl kullanılacağı hakkında daha fazla bilgi edinmek için Kalıcı iş başlıklı makaleyi inceleyin.
Optimize edilmiş veri kapsayıcıları kullanma
Programlama dili tarafından sağlanan sınıfların bazıları mobil cihazlarda kullanılmak üzere optimize edilmemiştir. Örneğin, genel HashMap uygulaması, her eşleme için ayrı bir giriş nesnesi gerektirdiğinden bellek açısından verimsiz olabilir.
Android çerçevesi, SparseArray, SparseBooleanArray ve LongSparseArray gibi çeşitli optimize edilmiş veri kapsayıcıları içerir. Örneğin, SparseArray sınıfları daha verimlidir. Çünkü sistemin anahtarı ve bazen de değeri otomatik olarak kutulamasına gerek kalmaz. Bu da her giriş için bir veya iki nesne daha oluşturur.
Gerekirse yalın bir veri yapısı için her zaman ham dizilere geçebilirsiniz.
Kod soyutlamalarıyla ilgili dikkatli olun
Geliştiriciler, kod esnekliğini ve bakımını iyileştirebildiği için genellikle iyi bir programlama uygulaması olarak soyutlamaları kullanır. Ancak soyutlamalar genellikle daha fazla kodun yürütülmesini gerektirir. Uygulamanızın kod ve kaynak ayak izini küçültme başlıklı makalede ayrıntılı olarak açıklandığı gibi, derlenmiş kod tabanının büyük olması uygulamanızın gerektirdiği fiziksel RAM'i doğrudan artırır. Soyutlamalarınız önemli ölçüde faydalı değilse bunları kullanmayın.
Serileştirilmiş veriler için lite protobuf'ları kullanma
Protokol arabellekleri (protobuf), Google tarafından yapılandırılmış verileri serileştirmek için tasarlanmış, dilden ve platformdan bağımsız, genişletilebilir bir mekanizmadır. XML'e benzer ancak daha küçük, daha hızlı ve daha basittir. Verileriniz için protobuf'ları kullanıyorsanız istemci tarafı kodunuzda her zaman lite protobuf'ları kullanın. Normal protobuf'lar, son derece ayrıntılı kod oluşturur. Bu da uygulamanızın RAM'deki kod alanını artırır (bkz. Uygulamanızın kod ve kaynak alanını azaltma) ve APK boyutunun artmasına neden olur.
Daha fazla bilgi için protobuf readme dosyasına bakın.
Bellek sızıntılarına karşı dikkatli olun
Uygunsuz referans yönetimi, nesnelerin yararlı ömürlerinden daha uzun süre yaşadığı bellek sızıntılarına yol açabilir ve çöp toplayıcının sızan nesnenin belleğini geri kazanmasını engelleyebilir. Bellek sızıntılarını önlemek için yaşam döngüsüne duyarlı tasarım uygulayın.
Bellek karmaşıklığından kaçının
Atık toplama etkinlikleri, uygulamanızın performansını etkilemez. Ancak kısa bir süre içinde gerçekleşen birçok atık toplama etkinliği, atık toplayıcı ile uygulama iş parçacıkları arasındaki gerekli etkileşimler nedeniyle pilin hızla tükenmesine ve karelerin ayarlanma süresinin biraz artmasına neden olabilir. Sistem, atık toplama işlemine ne kadar çok zaman harcarsa pil o kadar hızlı biter.
Bellek karmaşıklığı genellikle çok sayıda atık toplama etkinliğinin gerçekleşmesine neden olabilir. Pratikte bellek karmaşıklığı, belirli bir süre içinde ayrılan geçici nesnelerin sayısını ifade eder.
Örneğin, bir for döngüsünde birden fazla geçici nesne ayırabilirsiniz.
Alternatif olarak, bir görünümün onDraw() işlevi içinde yeni Paint veya Bitmap nesneleri de oluşturabilirsiniz. Her iki durumda da uygulama, yüksek hacimde hızlı bir şekilde çok sayıda nesne oluşturur. Bu tür nesneler, genç nesildeki tüm kullanılabilir belleği hızlıca tüketerek atık toplama etkinliğinin gerçekleşmesine neden olabilir.
Düzeltmeden önce kodunuzda bellek karmaşıklığının yüksek olduğu yerleri bulmak için Memory Profiler'ı kullanın.
Kodunuzdaki sorunlu alanları belirledikten sonra performansı etkileyen kritik alanlardaki ayırma sayısını azaltmaya çalışın. Öğeleri iç döngülerden veya fabrika tabanlı bir tahsis yapısına taşımayı deneyin.
Ayrıca nesne havuzlarının kullanım alanına fayda sağlayıp sağlamadığını da değerlendirebilirsiniz. Nesne havuzunda, nesne örneğini yere bırakmak yerine artık ihtiyaç duyulmadığında havuza bırakırsınız. Bu türden bir nesne örneğine bir sonraki ihtiyaç duyduğunuzda, onu ayırmak yerine havuzdan alabilirsiniz.
Bir nesne havuzunun belirli bir durumda uygun olup olmadığını belirlemek için performansı ayrıntılı bir şekilde değerlendirin. Nesne havuzlarının performansı kötüleştirebileceği durumlar vardır. Havuzlar tahsisleri önlese de başka ek yükler getirir. Örneğin, havuzun bakımı genellikle senkronizasyonu içerir ve bu da önemli bir ek yük oluşturur. Ayrıca, yayın sırasında bellek sızıntılarını önlemek için havuzdaki nesne örneğinin temizlenmesi ve ardından edinme sırasında başlatılması sıfır olmayan bir ek yüke neden olabilir.
Havuzda gerekenden daha fazla nesne örneği tutmak da atık toplama işlemine yük bindirir. Nesne havuzları çöp toplama çağrılarının sayısını azaltır ancak canlı (ulaşılabilir) bayt sayısıyla orantılı olduğundan her çağrı için gereken iş miktarını artırır.