Sobes.tech
Middle+

Как да определим наличието на теч на памет при анализ на дамп?

sobes.tech AI

Отговор от AI

За да откриете течове на памет в дамп (HPROF файл), се използват инструменти, които анализират графа на обектите в купчето. Основните стъпки:

  1. Получаване на дамп на паметта:

    • Чрез Memory Profiler в Android Studio.
    • С командата adb shell dumpheap <име на пакета> /data/local/tmp/dump.hprof.
    • Чрез системно извикване Debug.dumpHprofData(filePath).
  2. Анализ на дампа:

    • Отваряне на дампа в Android Studio: в Memory Profiler или чрез меню "File" -> "Open".
    • Анализ на обектите: сортирайте обектите по размер (Shallow Size, Retained Size) и брой.
    • Търсене на съмнителни обекти: търсете класове, които трябва да бъдат унищожени (например, Activity, Fragment, Contexts), но имат голям брой екземпляри или значителен Retained Size.
    • Изучаване на пътя към обекта (Reference Chain): изберете съмнителен обект и проследете пътя му към кореновите обекти (GC roots). Това ще покаже кой държи референцията, предотвратявайки събиране на боклука.
    • Търсене на статични референции: статичните полета често са източник на течове, ако съхраняват дълготрайни референции към контексти или изгледи.
    • Използване на LeakCanary: библиотеката автоматизира откриването, дампа и анализа на течове в реално време, предоставяйки подробна описание на пътя на теча.
  3. Интерпретация на резултатите:

    • Дълъг път към GC root, съдържащ референции към обекти, които трябва да бъдат унищожени, показва проблем.
    • Референции от статични полета, AsyncTask, Handlers с закъснения, неправилно отписани listeners/callbacks или singleton-и в активности или изгледи често са причина за течове.

Пример за анализ на пътя към GC root в Android Studio Memory Profiler:

// Пример за път към GC root, който показва теч
// android.app.Activity инстанция с mDestroyed=true
//   референция към android.widget.LinearLayout
//     референция към android.view.View $ListenerInfo
//       референция към com.example.MyActivity$1 (анонимен клас, реализиращ View.OnClickListener)
//         референция към com.example.MyActivity (референция, която причинява теч)

В този пример, анонимният клас (слушател на клик върху бутона) държи неявна референция към MyActivity, въпреки че активността вече трябва да е унищожена (mDestroyed=true). Този слушател изглежда е регистриран или задържан от друг дълготраен обект (например, статично поле или singleton).