Middle+
Jak wykryć wyciek pamięci podczas analizy zrzutu?
sobes.tech AI
Odpowiedź od AI
Aby wykryć wycieki pamięci w zrzucie (plik HPROF), używa się narzędzi analizujących graf obiektów na stercie. Główne kroki:
-
Uzyskanie zrzutu pamięci:
- Za pomocą Memory Profiler w Android Studio.
- Komendą
adb shell dumpheap <nazwa_pakietu> /data/local/tmp/dump.hprof. - Wywołaniem systemowym
Debug.dumpHprofData(filePath).
-
Analiza zrzutu:
- Otworzyć zrzut w Android Studio: w Memory Profiler lub przez menu "Plik" -> "Otwórz".
- Analiza obiektów: sortowanie obiektów według rozmiaru (Shallow Size, Retained Size) i liczby instancji.
- Wyszukiwanie podejrzanych obiektów: szukaj klas, które powinny zostać zniszczone (np. Activity, Fragment, Contexts), ale mają dużą liczbę instancji lub znaczny
Retained Size. - Badanie ścieżki do obiektu (Reference Chain): wybierz podejrzany obiekt i śledź jego ścieżkę do obiektów korzeniowych (GC roots). Pokaże to, kto utrzymuje odwołanie, zapobiegając zbieraniu śmieci.
- Wyszukiwanie referencji statycznych: pola statyczne często są źródłem wycieków, jeśli przechowują długotrwałe odwołania do kontekstów lub widoków.
- Użycie LeakCanary: biblioteka automatyzuje wykrywanie, zrzut i analizę wycieków w czasie rzeczywistym, dostarczając szczegółowy opis ścieżki wycieku.
-
Interpretacja wyników:
- Długa ścieżka do GC root zawierająca odwołania do obiektów, które powinny zostać zniszczone, wskazuje na problem.
- Odwołania z pól statycznych, AsyncTask, Handlerów z opóźnieniami, niepoprawnie odwołanych listenerów/callbacków lub singletonów w aktywnościach lub widokach często są przyczyną wycieków.
Przykład analizy ścieżki do GC root w Android Studio Memory Profiler:
// Przykład ścieżki do GC root wskazującej na wyciek
// android.app.Activity instancja z mDestroyed=true
// odwołanie do android.widget.LinearLayout
// odwołanie do android.view.View $ListenerInfo
// odwołanie do com.example.MyActivity$1 (klasa anonimowa implementująca View.OnClickListener)
// odwołanie do com.example.MyActivity (wskazanie wycieku)
W tym przykładzie, anonimowa klasa (nasłuchiwacz kliknięcia przycisku) utrzymuje domyślne odwołanie do MyActivity, mimo że aktywność powinna już zostać zniszczona (mDestroyed=true). Ten nasłuchiwacz wydaje się być zarejestrowany lub utrzymywany przez inny obiekt o długim czasie życia (np. pole statyczne lub singleton).