Sobes.tech
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:

  1. 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).
  2. 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.
  3. 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).