Bellek yönetimi için en iyi uygulamalar

Bu dokümanda, bellek yönetimiyle ilgili Android uygulamaları için en iyi uygulama yönergelerini (ör. Uygulamanızın belleğini yönetme) uyguladığınız varsayılır.

Giriş

Bellek sızıntısı, bir bilgisayar programının artık ihtiyaç duyulmayan ayrılmış belleği serbest bırakmaması durumunda meydana gelen bir kaynak sızıntısı türüdür. Sızıntı, uygulamanın işletim sisteminden sahip olduğundan daha fazla bellek istemesine ve dolayısıyla uygulamanın kilitlenmesine neden olabilir. Android uygulamalarında bellek sızıntılarına neden olabilecek çeşitli uygunsuz uygulamalar vardır. Örneğin, kaynakların uygun şekilde elden çıkarılmaması veya dinleyicilerin artık gerekmediğinde kaydının silinmemesi.

Bu belgede, kodunuzdaki bellek sızıntılarını önlemenize, tespit etmenize ve çözmenize yardımcı olacak bazı en iyi uygulamalar yer almaktadır. Bu belgedeki 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

Bellek sızıntısını Google Destek Ekibi'ne bildirmeden önce, hatanın kodunuzda olmadığından emin olmak için bu belgede sağlanan hata ayıklama adımlarıyla birlikte en iyi uygulamaları izleyin. Bu adımlar sorununuzu çözebilir. Çözmezse Google Destek Ekibi'nin size yardımcı olmak için ihtiyaç duyduğu bilgileri oluşturur.

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

Google SDK'larını kullanan kodda bellek sızıntısı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. Gerekli olmadığında görevleri iptal edin.
  4. Kaynakları serbest bırakmak için yaşam döngüsü yöntemlerini iletin.
  5. SDK'ların en yeni sürümlerini kullanın.
  6. ANR'leri önlemek için başlatma sırasında ana iş parçacığını engellemeyin.

Bu uygulamaların her biriyle ilgili 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 ihtiyaç duyulmadığında kaynağı serbest bıraktığınızdan emin olun. Aksi takdirde, uygulamanız bu kaynakları kullanmayı bıraktıktan sonra bile kaynaklar bellek kullanmaya devam eder. Daha fazla bilgi için Android belgelerindeki Etkinlik yaşam döngüsü konusunu inceleyin.

GeoSDK'lerde eski GoogleMap referanslarını serbest bırakma

Yaygın bir hata, NavigationView veya MapView kullanılarak önbelleğe alınan bir GoogleMap'in bellek sızıntısına neden olabilmesidir. Bir GoogleMap, alındığı NavigationView veya MapView ile bire bir ilişkiye sahiptir. GoogleMap'in önbelleğe alınmadığından veya NavigationView#onDestroy ya da 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ç duyulmadığında dinleyicilerin kaydını iptal etme

Android uygulamanız bir etkinlik için (ör. düğme tıklama veya görünüm durumunda değişiklik) dinleyici kaydettiğinde, uygulamanın artık etkinliği izlemesi gerekmediğinde dinleyicinin kaydını kaldırdığınızdan emin olun. Aksi takdirde, dinleyiciler uygulamanız onlarla işini bitirdikten sonra bile bellek kullanmaya devam eder.

Örneğin, uygulamanızın Navigation SDK'yı kullandığını ve varış etkinliklerini dinlemek için aşağıdaki işleyiciyi çağırdığını varsayalım: addArrivalListener varış etkinliklerini dinlemek için kullanılan yöntem, 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()
}

Gerekli olmayan görevleri iptal etme

Bir Android uygulaması, indirme veya ağ isteği gibi eşzamansız bir göreve başladığında görev tamamlandığında iptal ettiğinizden emin olun. Görev iptal edilmezse uygulama görevi tamamladıktan sonra bile arka planda çalışmaya devam eder.

En iyi uygulamalar hakkında daha fazla bilgi için Android belgelerindeki 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 iletme

Uygulamanızda Gezinme veya Haritalar SDK'sı kullanılıyorsa yaşam döngüsü yöntemlerini (kalın olarak gösterilmiştir) navView'ya yönlendirerek kaynakları serbest bıraktığınızdan emin olun. Bunu, Navigation SDK'da NavigationView veya Maps ya da Navigation SDK'da MapView kullanarak yapabilirsiniz. Ayrıca, doğrudan NavigationView ve MapView kullanmak yerine sırasıyla SupportNavigationFragment veya SupportMapFragment da kullanabilirsiniz. Destek parçaları, yaşam döngüsü yöntemlerinin yönlendirilmesini sağlar.

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 yeni sürümlerini kullanın

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

ANR'leri önlemek için başlatma sırasında ana iş parçacığını engellemeyin

Bir uygulama ana iş parçacığını çok uzun süre engellediğinde "Uygulama yanıt vermiyor" (ANR) hatasına neden olabilir. ANR'leri önlemek için uzun süren görevleri erteleyerek veya ana iş parçacığı dışında çalıştırarak onCreate() gibi yaşam döngüsü yöntemlerini mümkün olduğunca basit tutun.

SDK başlatmayla ilgili ANR'leri önlemek için:

  • Tek seferde yalnızca bir harita örneği oluşturun.
  • Harita oluşturulurken kullanıcı arayüzü iş parçacığındaki işi mümkün olduğunca azaltın.

Bellek sızıntılarında hata ayıklama

Bu belgenin önceki bölümlerinde geçerli olan tüm önerileri uyguladıktan sonra hala bellek sızıntıları görüyorsanız hata ayıklama için bu süreci izleyin.

Başlamadan önce Android'in belleği nasıl yönettiğini bilmeniz gerekir. Daha fazla bilgi için Android Bellek yönetimine genel bakış başlıklı makaleyi inceleyin.

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

  1. Sorunu yeniden oluşturun. Bu adım, hata ayıklama için gereklidir.
  2. Bellek kullanımının normal 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ığını kontrol edin.
  3. Üst düzeyde hata ayıklama. Hata ayıklamak için kullanabileceğiniz çeşitli yardımcı programlar vardır. Android'deki bellek sorunlarını ayıklamaya yardımcı olan üç farklı standart araç seti 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. Yığın dökümü ve bellek ayırma izleme bilgilerini alıp analiz edin.
  5. Bellek sızıntılarını düzeltme.

Aşağıdaki bölümlerde bu adımlar ayrıntılı olarak açıklanmaktadır.

1. adım: Sorunu yeniden oluşturun

Sorunu yeniden oluşturamadıysanız öncelikle bellek sızıntısına yol açabilecek senaryoları göz önünde bulundurun. Sorunun yeniden oluşturulduğunu biliyorsanız doğrudan yığın dökümüne bakmak işe yarayabilir. Ancak, uygulama başlatılırken veya başka bir rastgele zamanda yalnızca bir yığın dökümü alırsanız 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 özellikler etkinleştirilir?

  • Sızıntıyı tetikleyen belirli kullanıcı işlemleri sırası nedir?

    • Bu sırayı etkinleştirmek için birden çok deneme yaptınız mı?
  • Uygulama hangi yaşam döngüsü durumlarından geçti?

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

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

2. adım: Uygulamanın bellek kullanımının normal 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 aslında bir bellek sızıntısı olup olmadığını göz önünde bulundurun. Örneğin, farklı özellikler veya kullanıcı görevleri için aşağıdaki olasılıkları göz önünde bulundurun:

  • Muhtemelen sızıntı: Senaryoyu birden fazla yinelemeyle etkinleştirmek, zaman içinde bellek kullanımının artmasına neden olur.

  • Beklenen bellek kullanımı: Senaryo durdurulduktan sonra bellek geri kazanılır.

  • Olası beklenen bellek kullanımı: Bellek kullanımı bir süre artar ve sonra azalır. Bu durum, sınırlı bir önbellekten veya beklenen diğer bellek kullanımından kaynaklanabilir.

Uygulama davranışı beklenen bellek kullanımıyla uyumluysa sorun, uygulamanızın belleğini yöneterek çözülebilir. Yardım için Uygulamanızın belleğini yönetme başlıklı makaleye bakın.

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

Bellek sızıntısında hata ayıklarken yüksek bir seviyeden başlayın ve olasılıkları daralttıktan sonra ayrıntılara inin. Öncelikle zaman içinde sızıntı olup olmadığını analiz etmek için şu üst düzey hata ayıklama araçlarından birini kullanın:

Android Studio Memory Profiler

Bu araç, kullanılan belleğin görsel histogramını gösterir. Yığın dökümleri ve ayırma izleme de aynı arayüzden tetiklenebilir. Bu araç, varsayılan öneridir. Daha fazla bilgi için Android Studio Memory Profiler başlıklı makaleyi inceleyin.

Perfetto Bellek Sayaçları

Perfetto, çeşitli metriklerin izlenmesi üzerinde hassas kontrol sağlar ve tüm bunları tek bir histogramda 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 birçok şey, doğrudan sorgulayabileceğiniz bir adb komut satırı yardımcı programı olarak da kullanılabilir. Bu konuda birkaç önemli örnek:

  • Meminfo, belirli bir zamandaki ayrıntılı bellek bilgilerini görmenizi sağlar.

  • Procstats, 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 bellekte kaplanan yer (maxRSS) değeridir. 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.

Tahsis takibi

Tahsis izleme, belleğin tahsis edildiği ve boşaltılmadığı yığın izlemeyi tanımlar. Bu adım, özellikle yerel kodda sızıntıları izlerken yararlıdır. Bu araç, yığın izleme (stack trace) tanımladığından temel nedeni hızlı bir şekilde hata ayıklamak veya sorunu nasıl yeniden oluşturacağınızı bulmak için harika bir yöntem olabilir. Ayrım izlemeyi kullanma adımları için Ayrım izleme ile yerel kodda belleği hata ayıklama başlıklı makaleyi inceleyin.

4. adım: Yığın dökümüyle 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ı olup olmadığını incelemektir. 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ı tespit edebilir. Android Studio, yığın dökümü aldığınızda hâlâ erişilebilir olan ancak zaten yok edilmiş bir etkinlik veya parça olup olmadığını kontrol eder.

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

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

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

Yığın dökümü almak için Android Debug Bridge'i (adb) veya Android Studio Memory Profiler'ı kullanabilirsiniz.

Yığın dökümü almak 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. Bir komut istemi açın ve adb araçlarının bulunduğu dizine gidin.
  3. Yığın dökümü almak 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.

Yığın dökümü almak için Android Studio'yu kullanma

Android Studio Memory Profiler'ı kullanarak yığın dökümü almak için Android'deki Yığın dökümü alma bölümünde aşağıdaki adımları uygulayın.

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

Yığın dökümü yakaladıktan sonra, bunu analiz etmek için Android Studio Memory Profiler'ı kullanabilirsiniz. Bunu yapmak için şu adımları uygulayın:

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

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

  3. Android Profiler sekmesini açın.

  4. Bellek'i seçin.

  5. Open heap dump'ı (Yığın dökümü aç) ve oluşturduğunuz yığın dökümü dosyasını seçin. Bellek profil oluşturucu, 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 belirleyin.

    • Çok fazla bellek kullanan nesneleri belirleyin.

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

  7. Bellek sızıntısının kaynağını daraltmak veya bulmak ve sorunu düzeltmek 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ı düzeltmek, uygulamalarınızın performansını ve kararlılığını artırmaya yardımcı olur. Ayrıntılar senaryoya göre değişir. Ancak aşağıdaki öneriler yardımcı olabilir:

Diğer hata ayıklama araçları

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

Ayırma izleme ile yerel kodda bellekte hata ayıklama

Doğrudan yerel kod kullanmıyor olsanız bile Google SDK'ları dahil olmak üzere çeşitli yaygın Android kitaplıkları kullanır. Bellek sızıntınızın yerel kodda olduğunu düşünüyorsanız hata ayıklamak için çeşitli araçlar kullanabilirsiniz. Bellek sızıntısının olası nedenlerini belirlemek için Android Studio veya heapprofd (Perfetto ile de uyumludur) ile tahsis izleme harika bir yöntemdir ve genellikle en hızlı hata ayıklama yoludur.

Ayrıca, tahsis izleme, sonuçları yığın halinde bulunabilecek hassas bilgiler olmadan paylaşmanıza olanak tanıyan ayrı bir avantaja da sahiptir.

LeakCanary ile bellek sızıntılarını 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 kullanma hakkında daha fazla bilgi edinmek için LeakCanary'yi 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 çok ekleyerek müşteri destek ekibiyle iletişime geçin:

  • Bellek sızıntısını yeniden oluşturma adımları. Adımlar karmaşık kodlama gerektiriyorsa sorunu kopyalayan kodu örnek uygulamamıza kopyalamak ve sızıntıyı tetiklemek için kullanıcı arayüzünde yapılması gereken ek adımları sağlamak yardımcı 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 yakalayın.

  • Yerel bir bellek sızıntısı bekleniyorsa, heapprofd'den alınan bellek ayırma izleme çıkışını paylaşın.

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

  • Bellekle ilgili kilitlenmelerin yığın izlemeleri.

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