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. Bir sızıntı, uygulamanın işletim sisteminden mevcut olandan daha fazla bellek istemesine ve dolayısıyla uygulamanın kilitlenmesine 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ı durumunu Google Destek Ekibi'ne bildirmeden önce, hatanın kodunuzda olmadığından emin olmak için bu dokümanda sağlanan hata ayıklama adımlarıyla birlikte en iyi uygulamaları takip edin. 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ıları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 birine ilişkin ayrıntılar için aşağıdaki bölümlere bakın.

Kullanılmayan kaynakları serbest bırakın

Android uygulamanız bir kaynak kullandığında, artık gerekli olmadığında kaynağı serbest bıraktığınızdan emin olun. Aksi takdirde, kaynak, uygulamanız bu kaynakları kullanmayı bıraktıktan sonra bile bellek 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

Google Haritalar'ın, NavigationView veya MapView kullanılarak önbelleğe alınması durumunda bellek sızıntısı oluşmasına neden olabileceği sık karşılaşılan bir hatadır. GoogleMap, alındığı NavigationView veya MapView ile 1'e 1 ilişkiye sahiptir. Bir Google haritasının önbelleğe alınmadığından ya da 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ılıyorsa referans,Fragment#onDestroyView uygulamasında yayınlanmalı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 Navigation SDK'sında NavigationView veya Haritalar ya da Navigation 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 işler.

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 dokümanın önceki kısımlarında geçerli tüm önerileri uyguladıktan sonra da bellek sızıntıları görmeye devam ediyorsanız hata ayıklamak için bu işlemi uygulayın.

Başlamadan önce Android'in belleği nasıl yönettiği hakkında bilgi sahibi olmanız gerekir. Daha fazla bilgi için Android Bellek yönetimine genel bakış sayfasını 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 beklenip beklenmediğini kontrol edin. Sızıntı gibi görünen artan kullanımın, uygulamanızı çalıştırmak için gereken bellek olmadığından emin olun.
  3. Üst düzeyde hata ayıklayın. 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 yığın dökümünü almanız, bir sızıntıyı tetikleyecek koşulları etkinleştirmediğiniz anlamına gelebilir. 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 diziyi etkinleştirmek için tekrar tekrar 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 en son SDK sürümünde yeniden oluşturabildiğinizden emin olun. Önceki bir sürümden kaynaklanan sorun zaten düzeltilmiş olabilir.

2. Adım: Uygulama için bellek kullanımının beklenip beklenmediğini 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:

  • Olası sızıntı: Senaryonun birden fazla iterasyon ile etkinleştirilmesi, zaman içinde bellek kullanımında artışa 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 konusuna bakın.

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 ayırma 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 hata ayıklama köprüsü (adb) komut satırı yardımcı programları

Perfetto ile izleyebileceğiniz içeriklerin birçoğu, doğrudan sorgulayabileceğiniz bir adb komut satırı yardımcı programı olarak da mevcuttur. 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ın veya sorunun nasıl yeniden oluşturulacağını anlamanın mükemmel bir yolu olabilir. Ayırma izlemeyi kullanma adımları için Tahsis izleme ile yerel kodda bellek hatalarını ayıklama bölümüne bakın.

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 küme dökümü 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ü yakalayın

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 bir yığın dökümünü yakalamak için şu 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ılarını 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ıkla yapılandırmasını seçin.

  3. Android Profilleyici sekmesini açın.

  4. Bellek'i seçin.

  5. Yığın dökümünü aç'ı ve oluşturduğunuz yığın dökümü dosyasını seçin. Bellek profil aracı, uygulamanızın bellek kullanımının bir 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 belirleme

    • 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 bunu düzeltebilirsiniz. Android uygulamalarınızdaki bellek sızıntılarını düzeltmek, uygulamalarınızın performansını ve kararlılığını iyileştirmeye 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, bellek sızıntısını hâlâ bulamadıysanız ve sorunu gideremediyseniz şu araçları deneyin:

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

Doğrudan yerel kodu kullanmasanız bile Google SDK'ları dahil olmak üzere bazı yaygın Android kitaplıkları bunu 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çlardan yararlanabilirsiniz. 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 edin

LeakCanary, Android uygulamalarındaki bellek sızıntılarını tanımlamak 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'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 mümkün olduğunca çoğunu sağlayarak müşteri desteğine başvurun:

  • 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 bir 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 izleme (stack trace), bellek sorununda hata ayıklamak için genellikle tek başına yeterli değildir. Bu nedenle, diğer bilgi biçimlerinden birini de sağladığınızdan emin olun.