Middle+
Как да определим наличието на теч на памет при анализ на дамп?
sobes.tech AI
Отговор от AI
За да откриете течове на памет в дамп (HPROF файл), се използват инструменти, които анализират графа на обектите в купчето. Основните стъпки:
-
Получаване на дамп на паметта:
- Чрез Memory Profiler в Android Studio.
- С командата
adb shell dumpheap <име на пакета> /data/local/tmp/dump.hprof. - Чрез системно извикване
Debug.dumpHprofData(filePath).
-
Анализ на дампа:
- Отваряне на дампа в Android Studio: в Memory Profiler или чрез меню "File" -> "Open".
- Анализ на обектите: сортирайте обектите по размер (Shallow Size, Retained Size) и брой.
- Търсене на съмнителни обекти: търсете класове, които трябва да бъдат унищожени (например, Activity, Fragment, Contexts), но имат голям брой екземпляри или значителен
Retained Size. - Изучаване на пътя към обекта (Reference Chain): изберете съмнителен обект и проследете пътя му към кореновите обекти (GC roots). Това ще покаже кой държи референцията, предотвратявайки събиране на боклука.
- Търсене на статични референции: статичните полета често са източник на течове, ако съхраняват дълготрайни референции към контексти или изгледи.
- Използване на LeakCanary: библиотеката автоматизира откриването, дампа и анализа на течове в реално време, предоставяйки подробна описание на пътя на теча.
-
Интерпретация на резултатите:
- Дълъг път към 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).