Bellek yönetimi için en iyi uygulamalar

Bu dokümanda, bellek yönetimi kapsamında Android uygulamaları için en iyi uygulamalarla ilgili yönergelere (ör. Uygulamanızın belleğini yönetme) uyduğunuz varsayılmaktadır.

Giriş

Bellek sızıntısı, bir bilgisayar programı artık ihtiyaç duyulmayan ayrılmış belleği serbest bırakmadığında ortaya çıkan bir tür kaynak sızıntısıdır. Sızıntı, uygulamanın işletim sisteminden sahip olduğundan daha fazla bellek istemesine ve dolayısıyla uygulamanın çökmesine neden olabilir. Kaynakların düzgün şekilde kullanılmaması veya artık gerekli olmadığında dinleyicilerin kaydının silinmemesi gibi bazı yanlış uygulamalar Android uygulamalarında bellek sızıntısına neden olabilir.

Bu dokümanda, kodunuzdaki bellek sızıntılarını önlemeye, tespit etmeye ve çözmeye yardımcı olacak bazı en iyi uygulamalar sunulmaktadır. Bu dokümandaki yöntemleri denediyseniz ve SDK'larımızda bellek sızıntısı olduğundan şüpheleniyorsanız Google SDK'larıyla ilgili sorunları bildirme başlıklı makaleyi inceleyin.

Destek ekibiyle iletişime geçmeden önce

Bir bellek sızıntısını Google destek ekibine bildirmeden önce, hatanın kodunuzda olmadığından emin olmak için bu belgede verilen hata ayıklama adımlarının yanı sıra en iyi uygulamaları uygulayın. Bu adımlar sorununuzu çözebilir. Çözüm bulamazsa Google Destek Ekibi'nin size yardımcı olması için gereken bilgileri oluşturur.

Bellek sızıntısını önleme

Google SDK'larını kullanan kodda hafıza sızıntısı sorunlarının en yaygın nedenlerinden bazılarını önlemek için aşağıdaki en iyi uygulamalardan yararlanın.

Android uygulamaları için en iyi uygulamalar

Android uygulamanızda aşağıdakilerin tümünü yaptığınızdan emin olun:

  1. Kullanılmayan kaynakları serbest bırakın.
  2. Artık ihtiyaç duyulmadığında dinleyicilerin kaydını iptal edin.
  3. Gerekmediğinde görevleri iptal edin.
  4. Kaynakları serbest bırakmak için yaşam döngüsü yöntemlerini iletin.
  5. SDK'ların en son sürümlerini kullanın

Bu uygulamaların her biri hakkında ayrıntılı bilgi için aşağıdaki bölümlere bakın.

Kullanılmayan kaynakları serbest bırakma

Android uygulamanız bir kaynak kullandığında, artık gerekli olmadığında kaynağı serbest bıraktığınızdan emin olun. Aksi takdirde, uygulamanız bu kaynakları kullanmayı bıraktıktan sonra bile kaynak hafıza kullanmaya devam eder. Daha fazla bilgi için Android dokümanlarında Etkinlik yaşam döngüsü bölümünü inceleyin.

GeoSDK'lerde eski Google Haritalar referanslarını kaldırma

NavigationView veya MapView kullanılarak önbelleğe alınan bir GoogleMap'in bellek sızıntısına neden olabileceği yaygın bir hatadır. GoogleMap, alındığı NavigationView veya MapView ile 1'e 1 ilişkiye sahiptir. Bir GoogleMap'in önbelleğe alınmadığından veya NavigationView#onDestroy veya MapView#onDestroy çağrıldığında referansın serbest bırakıldığından emin olmanız gerekir. NavigationSupportFragment, MapSupportFragment veya bu görünümleri sarmalayan kendi parçanızı kullanıyorsanız referans, Fragment#onDestroyView içinde serbest bırakılmalıdır.

class NavFragment : SupportNavigationFragment() {

  var googleMap: GoogleMap?

  override fun onCreateView(
    inflater: LayoutInflater,
    parent: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View  {
    super.onCreateView(inflater,parent,savedInstanceState)
    getMapAsync{map -> googleMap = map}
  }

  override fun onDestroyView() {
    googleMap = null
  }
}

Artık ihtiyaç duyulmayan dinleyicilerin kaydını silme

Android uygulamanız bir etkinlik için dinleyici kaydettiğinde (ör. düğme tıklaması veya bir görünümün durumundaki değişiklik), uygulamanın artık etkinliği izlemesi gerekmediğinde dinleyicinin kaydını sildiğinizden emin olun. Aksi takdirde, dinleyiciler uygulamanızla ilgili işlemleri tamamladıktan sonra bile bellek kullanmaya devam eder.

Örneğin, uygulamanızın Navigasyon SDK'sını kullandığını ve varış etkinliklerini dinlemek için aşağıdaki dinleyiciyi çağırdığını varsayalım: addArrivalListener yöntemi çağırır. Ayrıca, artık varış etkinliklerini izlemesi gerekmediğinde removeArrivalListener yöntemini de çağırmalıdır.

var arrivalListener: Navigator.ArrivalListener? = null

fun registerNavigationListeners() {
  arrivalListener =
    Navigator.ArrivalListener {
      ...
    }
  navigator.addArrivalListener(arrivalListener)
}

override fun onDestroy() {
  navView.onDestroy()
  if (arrivalListener != null) {
    navigator.removeArrivalListener(arrivalListener)
  }

  ...
  super.onDestroy()
}

Gerekmediğinde görevleri iptal etme

Bir Android uygulaması, indirme veya ağ isteği gibi asenkron bir görev başlattığında, görev tamamlandığında iptal ettiğinizden emin olun. Görev iptal edilmezse uygulamanın görevi tamamlamasından sonra bile arka planda çalışmaya devam eder.

En iyi uygulamalar hakkında daha fazla bilgi için Android dokümanlarında Uygulamanızın belleğini yönetme başlıklı makaleyi inceleyin.

Kaynakları serbest bırakmak için yaşam döngüsü yöntemlerini yönlendirme

Uygulamanız Navigasyon veya Haritalar SDK'sını kullanıyorsa yaşam döngüsü yöntemlerini (kalın olarak gösterilir) navView adresine yönlendirerek kaynakları serbest bıraktığınızdan emin olun. Bunu Navigasyon SDK'sında NavigationView veya Haritalar ya da Navigasyon SDK'sında MapView kullanarak yapabilirsiniz. Doğrudan NavigationView ve MapView yerine SupportNavigationFragment veya SupportMapFragment kullanabilirsiniz. Destek parçaları, yaşam döngüsü yöntemlerinin yönlendirilmesini yönetir.

class NavViewActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    navView = ...
    navView.onCreate(savedInstanceState)
    ...
  }

  override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)
    navView.onSaveInstanceState(savedInstanceState)
  }

  override fun onTrimMemory(level: Int) {
    super.onTrimMemory(level)
    navView.onTrimMemory(level)
  }

  /* Same with
    override fun onStart()
    override fun onResume()
    override fun onPause()
    override fun onConfigurationChanged(...)
    override fun onStop()
    override fun onDestroy()
  */
}

SDK'ların en son sürümlerini kullanın

Google SDK'ları yeni özellikler, hata düzeltmeleri ve performans iyileştirmeleriyle sürekli olarak güncellenir. Bu düzeltmeleri almak için uygulamanızdaki SDK'ları güncel tutun.

Bellek sızıntısı sorunlarını ayıklama

Bu belgenin önceki bölümlerinde yer alan tüm geçerli önerileri uyguladıktan sonra hâlâ bellek sızıntısı görüyorsanız hata ayıklama için bu süreci uygulayın.

Başlamadan önce Android'in belleği nasıl yönettiği hakkında bilgi sahibi olmanız gerekir. Bilgi için Android Bellek yönetimine genel bakış başlıklı makaleyi okuyun.

Bellek sızıntılarını ayıklamak için aşağıdaki işlemi uygulayın:

  1. Sorunu yeniden oluşturun. Bu adım, hata ayıklama için gereklidir.
  2. Bellek kullanımının beklenen düzeyde olup olmadığını kontrol edin. Sızıntı gibi görünen artan kullanımın aslında uygulamanızı çalıştırmak için gereken bellek olmadığından emin olun.
  3. Yüksek düzeyde hata ayıklama. Hata ayıklama için kullanabileceğiniz çeşitli yardımcı programlar vardır. Android'deki bellek sorunlarını gidermeye yardımcı olan üç farklı standart araç grubu vardır: Android Studio, Perfetto ve Android Debug Bridge (adb) komut satırı yardımcı programları.
  4. Uygulamanızın bellek kullanımını kontrol edin. Bir yığın dökümü ve tahsis izlemesi alın ve ardından bunları analiz edin.
  5. Bellek sızıntılarını düzeltin.

Aşağıdaki bölümlerde bu adımlar ayrıntılı olarak ele alınmaktadır.

1. adım: Sorunu yeniden oluşturun

Sorunu yeniden oluşturamadıysanız önce bellek sızıntısına neden olabilecek senaryoları göz önünde bulundurun. Sorunun yeniden oluşturulduğunu biliyorsanız doğrudan bir yığın dökümüne bakmak işe yarayabilir. Ancak, uygulamanın başlatılması veya rastgele bir zamanda bir yığın dökümü alırsanız bir sızıntıyı tetikleyecek koşulları etkinleştirmemiş olabilirsiniz. Sorunu yeniden oluşturmaya çalışırken çeşitli senaryoları göz önünde bulundurun:

  • Hangi özellik grubu etkinleştirilir?

  • Sızıntıyı tetikleyen belirli bir kullanıcı işlemi dizisi var mı?

    • Bu sırayı etkinleştirmek için birden fazla iterasyon denediniz mi?
  • Uygulama hangi yaşam döngüsü durumlarında bulundu?

    • Farklı yaşam döngüsü durumlarında birden fazla iterasyon denediniz mi?

Sorunu SDK'ların en son sürümünde yeniden oluşturabileceğinizden emin olun. Önceki sürümdeki sorun zaten düzeltilmiş olabilir.

2. adım: Uygulamanın bellek kullanımının beklenen düzeyde olup olmadığını kontrol edin

Her özellik için ek bellek gerekir. Farklı senaryolarda hata ayıklama yaparken bunun beklenen bir kullanım olup olmadığını veya gerçekten bir bellek sızıntısı olup olmadığını düşünün. Örneğin, farklı özellikler veya kullanıcı görevleri için aşağıdaki olasılıkları göz önünde bulundurun:

  • Büyük olasılıkla sızıntı: Senaryoyu birden fazla iterasyonla etkinleştirmek, zaman içinde bellek kullanımının artmasına neden olur.

  • Beklenen bellek kullanımı: Senaryo durdurulduktan sonra bellek geri alınır.

  • Olası beklenenden bellek kullanımı: Bellek kullanımı bir süre boyunca artar, ardından azalır. Bu durum, sınırlı bir önbellekten veya beklenenden başka bir bellek kullanımından kaynaklanabilir.

Uygulama davranışı büyük olasılıkla beklenen bellek kullanımıysa sorunu, uygulamanızın belleğini yöneterek çözebilirsiniz. Yardım için Uygulamanızın belleğini yönetme başlıklı makaleyi inceleyin.

3. adım: Yüksek düzeyde hata ayıklama

Bir bellek sızıntısında hata ayıklama işlemine yüksek düzeyden başlayın ve olasılıkları daralttıktan sonra ayrıntılı inceleme yapın. Öncelikle zaman içinde sızıntı olup olmadığını analiz etmek için aşağıdaki üst düzey hata ayıklama araçlarından birini kullanın:

Android Studio Memory Profiler

Bu araç, kullanılan belleğin görsel bir histogramini sunar. Yığın dökümleri ve tahsis izleme de aynı arayüzden tetiklenebilir. Bu araç, varsayılan öneridir. Daha fazla bilgi için Android Studio Bellek Profilleyicisi başlıklı makaleyi inceleyin.

Perfetto Bellek Sayaçları

Perfetto, çeşitli metrikleri izleme konusunda hassas kontrol sağlar ve tüm metrikleri tek bir histogramde sunar. Daha fazla bilgi için Perfetto Bellek Sayaçları başlıklı makaleyi inceleyin.

Perfetto kullanıcı arayüzü

Android Debug Bridge (adb) komut satırı yardımcı programları

Perfetto ile izleyebileceğiniz verilerin çoğu, doğrudan sorgulayabileceğiniz bir adbkomut satırı yardımcı programı olarak da kullanılabilir. Birkaç önemli örnek:

  • Meminfo, belirli bir zamanda ayrıntılı hafıza bilgilerini görmenize olanak tanır.

  • İşlem istatistikleri, zaman içinde bazı önemli toplu istatistikler sağlar.

Burada dikkat edilmesi gereken önemli bir istatistik, uygulamanın zaman içinde ihtiyaç duyduğu maksimum fiziksel bellek alanı (maxRSS) boyutudur. MaxPSS o kadar doğru olmayabilir. Doğruluğu artırmanın bir yolu için adb shell dumpsys procstats --help –start-testing işaretine bakın.

Ayırma izleme

Tahsis izleme, belleğin tahsis edildiği yığın izlemeyi ve belleğin boşaltılıp boşaltılmadığını tanımlar. Bu adım, özellikle yerel koddaki sızıntıları tespit ederken yararlıdır. Bu araç yığın izlemeyi tanımladığından, temel nedenin hata ayıklamasını hızlıca yapmanıza veya sorunun nasıl yeniden oluşturulacağını anlamanıza yardımcı olabilir. Ayırma izlemeyi kullanma adımları için Ayırma izleme ile yerel kodda bellek hatalarını ayıklama başlıklı makaleyi inceleyin.

4. Adım: Bir yığın dökümü kullanarak uygulamanızın bellek kullanımını kontrol edin

Bellek sızıntısını tespit etmenin bir yolu, uygulamanızın yığın dökümünü alıp sızıntıyı kontrol etmektir. Yığın dökümü, bir uygulamanın belleğindeki tüm nesnelerin anlık görüntüsüdür. Bellek sızıntılarını ve bellekle ilgili diğer sorunları teşhis etmek için kullanılabilir.

Android Studio, GC tarafından düzeltilemeyen bellek sızıntılarını algılayabilir. Bir yığın dökümü yakaladığınızda Android Studio, hâlâ erişilebilir durumda olan ancak zaten yok edilmiş bir etkinlik veya parça olup olmadığını kontrol eder.

  1. Bellek yığını dökümü alın.
  2. Bellek sızıntısı bulmak için yığın dökümünü analiz edin.
  3. Bellek sızıntılarını düzeltin.

Ayrıntılar için aşağıdaki bölümlere bakın.

Yığın dökümü yakalama

Bellek yığını dökümü yakalamak için Android Debug Bridge'i (adb) veya Android Studio Bellek Profilleyici'yi kullanabilirsiniz.

Yığın dökümünü yakalamak için adb'yi kullanma

adb kullanarak yığın dökümü almak için aşağıdaki adımları uygulayın:

  1. Android cihazınızı bilgisayarınıza bağlayın.
  2. Komut istemi açın ve adb araçlarının bulunduğu dizine gidin.
  3. Bir yığın dökümünü yakalamak için şu komutu çalıştırın :

    adb shell am dumpheap my.app.name $PHONE_FILE_OUT

  4. Yığın dökümünü almak için şu komutu çalıştırın:

    adb pull $PHONE_FILE_OUT $LOCAL_FILE.

Bellek yığını dökümü yakalamak için Android Studio'yu kullanma

Android Studio Bellek Profilleyici'yi kullanarak bir yığın dökümü yakalamak için Android Yığın dökümü yakalama bölümündeki adımları uygulayın.

Bellek sızıntısı bulmak için yığın dökümünü analiz etme

Bir yığın dökümü yakaladıktan sonra, Android Studio Bellek Profilleyici'yi kullanarak bu dökümanı analiz edebilirsiniz. Bunu yapmak için şu adımları uygulayın:

  1. Android Studio'da Android projenizi açın.

  2. Çalıştır'ı, ardından Hata ayıklama yapılandırmasını seçin.

  3. Android Profilleyici sekmesini açın.

  4. Hafıza'yı seçin.

  5. Yığın dökümünü aç'ı ve oluşturduğunuz yığın dökümünü seçin. Bellek profilleyici, uygulamanızın bellek kullanımının grafiğini gösterir.

  6. Yığın dökümünü analiz etmek için grafiği kullanın:

    • Artık kullanılmayan nesneleri tanımlayın.

    • Çok fazla bellek kullanan nesneleri tanımlama

    • Her nesnenin ne kadar bellek kullandığını görebilirsiniz.

  7. Bellek sızıntısının kaynağını daraltmak veya bulmak ve sorunu gidermek için bu bilgileri kullanın.

5. adım: Bellek sızıntılarını düzeltin

Bellek sızıntısının kaynağını belirledikten sonra sorunu düzeltebilirsiniz. Android uygulamalarınızdaki bellek sızıntılarının düzeltilmesi, uygulamalarınızın performansını ve kararlılığını artırmaya yardımcı olur. Ayrıntılar senaryoya bağlı olarak değişir. Ancak aşağıdaki öneriler yardımcı olabilir:

Diğer hata ayıklama araçları

Bu adımlar tamamlandıktan sonra hâlâ bellek sızıntısını bulup düzeltmediyseniz aşağıdaki araçları deneyin:

Ayırma izleme özelliğiyle yerel kodda bellek hatalarını ayıklayın

Doğrudan doğal kod kullanmıyor olsanız bile Google SDK'ları da dahil olmak üzere birçok yaygın Android kitaplığı doğal kod kullanır. Bellek sızıntısının yerel kodda olduğunu düşünüyorsanız hata ayıklama için kullanabileceğiniz çeşitli araçlar vardır. Android Studio veya heapprofd (Perfetto ile de uyumludur) ile ayırma izleme, bellek sızıntısının olası nedenlerini belirlemenin mükemmel bir yoludur ve genellikle hata ayıklamanın en hızlı yoludur.

Ayırma izlemenin bir diğer avantajı da, sonuçları bir yığınta bulunabilecek hassas bilgileri içermeden paylaşmanıza olanak tanımasıdır.

LeakCanary ile sızıntıları tespit etme

LeakCanary, Android uygulamalarındaki bellek sızıntılarını tespit etmek için kullanılan güçlü bir araçtır. LeakCanary'yi uygulamanızda nasıl kullanacağınız hakkında daha fazla bilgi edinmek için LeakCanary sayfasını ziyaret edin.

Google SDK'larıyla ilgili sorunları bildirme

Bu belgedeki yöntemleri denediyseniz ve SDK'larımızda bellek sızıntısı olduğundan şüpheleniyorsanız aşağıdaki bilgilerden olabildiğince fazlasını ekleyerek müşteri desteğiyle iletişime geçin:

  • Bellek sızıntısını yeniden oluşturma adımları. Adımlar karmaşık kodlama gerektiriyorsa sorunun tekrarlandığı kodu örnek uygulamamıza kopyalamak ve sızıntıyı tetiklemek için kullanıcı arayüzünde uygulanması gereken ek adımları sağlamak yararlı olabilir.

  • Sorunun yeniden oluşturulduğu uygulamanızdan alınan yığın dökümleri. Bellek kullanımının önemli ölçüde arttığını gösteren iki farklı zamanda yığın dökümleri alın.

  • Doğal bellek sızıntısı bekleniyorsa heapprofd'den ayırma izleme çıktısını paylaşın.

  • Sızıntı durumunu yeniden oluşturduktan sonra alınan bir hata raporu.

  • Bellekle ilgili kilitlenmelerin yığın izlemeleri.

    Önemli not: Yığın izlemeler genellikle bir bellek sorununu ayıklamak için tek başına yeterli değildir. Bu nedenle, diğer bilgi biçimlerinden birini de sağladığınızdan emin olun.