Zrób zrzut stosu

Zrób zrzut sterty, aby sprawdzić, które obiekty w aplikacji zużywają pamięć w momencie zrobienia zrzutu, i wykryć wycieki pamięci lub zachowanie związane z alokacją pamięci, które prowadzi do zacinania się, zawieszania, a nawet awarii aplikacji. Jest to szczególnie przydatne w przypadku zrzutów sterty po dłuższej sesji użytkownika, gdy mogą one pokazywać obiekty, które nadal znajdują się w pamięci, a nie powinny już tam być.

Na tej stronie opisujemy narzędzia, które Android Studio udostępnia do zbierania i analizowania zrzutów sterty. Możesz też sprawdzić pamięć aplikacji z poziomu wiersza poleceń za pomocą polecenia dumpsys, a także wyświetlić zdarzenia odśmiecania pamięci (GC) w Logcat.

Dlaczego warto profilować pamięć aplikacji

Android udostępnia zarządzane środowisko pamięci – gdy Android stwierdzi, że aplikacja nie używa już niektórych obiektów, moduł odśmiecania zwalnia nieużywaną pamięć i przywraca ją do sterty. Sposób, w jaki Android wyszukuje nieużywaną pamięć, jest stale ulepszany, ale w pewnym momencie we wszystkich wersjach Androida system musi na chwilę wstrzymać Twój kod. Zazwyczaj przerwy są niezauważalne. Jeśli jednak aplikacja przydziela pamięć szybciej, niż system jest w stanie ją odzyskać, może dojść do opóźnienia w jej działaniu, ponieważ moduł odzyskiwania pamięci będzie musiał zwolnić wystarczającą ilość pamięci, aby zaspokoić potrzeby aplikacji. Opóźnienie może spowodować pomijanie klatek przez aplikację i widoczne spowolnienie.

Nawet jeśli aplikacja nie działa wolno, ale ma wycieki pamięci, może ją zachowywać nawet wtedy, gdy działa w tle. Takie zachowanie może spowolnić działanie pamięci w pozostałej części systemu, ponieważ wymusza niepotrzebne zdarzenia odśmiecania pamięci. W końcu system musi zakończyć proces aplikacji, aby odzyskać pamięć. Gdy użytkownik wróci do aplikacji, proces aplikacji musi zostać całkowicie ponownie uruchomiony.

Informacje o praktykach programowania, które mogą zmniejszyć zużycie pamięci przez aplikację, znajdziesz w artykule Zarządzanie pamięcią aplikacji.

Omówienie zrzutu stosu

Aby zarejestrować zrzut sterty, wybierz zadanie Analizuj wykorzystanie pamięci (zrzut sterty) (użyj Profilera: uruchom „aplikację” jako aplikację z możliwością debugowania (pełne dane)). Podczas zrzucania sterty ilość pamięci Javy może tymczasowo wzrosnąć. To normalne, ponieważ zrzut stosu jest tworzony w tym samym procesie co aplikacja i do zebrania danych wymaga pewnej ilości pamięci. Po przechwyceniu zrzutu sterty zobaczysz:

Widok zrzutu sterty w profilerze Android Studio.

Lista zajęć zawiera te informacje:

  • Allocations (Alokacje): liczba alokacji w stercie.
  • Native Size (Rozmiar natywny): łączna ilość pamięci natywnej używanej przez ten typ obiektu (w bajtach). W przypadku niektórych obiektów przydzielonych w Javie zobaczysz tutaj pamięć, ponieważ Android używa pamięci natywnej w przypadku niektórych klas platformy, takich jak Bitmap.

  • Shallow Size (Rozmiar płytki): łączna ilość pamięci Javy używanej przez ten typ obiektu (w bajtach).

  • Zachowany rozmiar: łączny rozmiar pamięci zachowanej z powodu wszystkich instancji tej klasy (w bajtach).

Użyj menu puli, aby odfiltrować określone pule:

  • Stos aplikacji (domyślny): główny stos, na którym aplikacja przydziela pamięć.
  • Stos obrazów: obraz rozruchowy systemu zawierający klasy wstępnie wczytywane podczas uruchamiania. Przydziały w tym miejscu nigdy nie są przenoszone ani usuwane.
  • Stos Zygote: stos kopiowany przy zapisie, z którego w systemie Android rozwidla się proces aplikacji.

W menu wybierz sposób rozmieszczenia przydziałów:

  • Uporządkuj według zajęć (domyślnie): grupuje wszystkie przydziały na podstawie nazwy zajęć.
  • Uporządkuj według pakietu: grupuje wszystkie przydziały na podstawie nazwy pakietu.

Użyj menu zajęć, aby odfiltrować grupy zajęć:

  • Wszystkie klasy (domyślnie): wyświetla wszystkie klasy, w tym klasy z bibliotek i zależności.
  • Pokaż wycieki aktywności/fragmentów: pokazuje klasy, które powodują wycieki pamięci.
  • Pokaż klasy projektu: wyświetla tylko klasy zdefiniowane przez Twój projekt.

Kliknij nazwę klasy, aby otworzyć panel Instancja. Każda wymieniona instancja zawiera te elementy:

  • Głębokość: najmniejsza liczba przeskoków od dowolnego korzenia GC do wybranej instancji.
  • Rozmiar natywny: rozmiar tej instancji w pamięci natywnej. Ta kolumna jest widoczna tylko na urządzeniach z Androidem 7.0 lub nowszym.
  • Rozmiar płytki: rozmiar tej instancji w pamięci Javy.
  • Rozmiar zachowany: rozmiar pamięci, w której ta instancja dominuje (zgodnie z drzewem dominatorów).

Kliknij instancję, aby wyświetlić szczegóły instancji, w tym jej pola i odwołania. Typowe typy pól i odwołań to typy strukturalne, tablice i proste typy danych w języku Java. Kliknij prawym przyciskiem myszy pole lub odwołanie, aby przejść do powiązanego wystąpienia lub wiersza w kodzie źródłowym.

  • Pola: wyświetla wszystkie pola w tej instancji.
  • Odwołania: pokazuje wszystkie odwołania do obiektu wyróżnionego na karcie Instancja.
Widoki Instancje, PolaOdwołania w oknie narzędzia Zrzut pamięci.

Wykrywanie zduplikowanych bitmap

Począwszy od Androida Studio Narwhal 4 możesz też wykrywać nadmiarowe mapy bitowe w widoku zrzutu sterty.

Oto jak je znaleźć:

  1. Otwieranie karty Profiler w Android Studio
  2. Kliknij Heap Dump (lub Analyze Memory Usage) i kliknij nagrywanie, aby zrobić migawkę bieżącego stanu pamięci aplikacji.
  3. Przejrzyj wyniki analizy i poszukaj żółtego trójkąta ostrzegawczego ⚠️, którego Android Studio używa do oznaczania zduplikowanych bitmap przechowywanych wielokrotnie.
    • Możesz też przejść do nagłówka profilera, kliknąć Filtruj według: i wybrać ustawienie Zduplikowane mapy bitowe.
  4. Kliknij dowolny oznaczony wpis, aby otworzyć panel Podgląd mapy bitowej. Dzięki temu zobaczysz, który obraz jest powielany.
  5. Wykorzystaj to wizualne potwierdzenie, aby odnaleźć w kodzie zbędną logikę wczytywania i wdrożyć lepszą strategię buforowania.
Poszukaj zduplikowanych bitmap, korzystając z żółtego trójkąta ostrzegawczego ⚠️.

Wykrywanie wycieków pamięci

Aby szybko odfiltrować klasy, które mogą być powiązane z wyciekami pamięci, otwórz menu klas i kliknij Pokaż wycieki aktywności lub fragmentów. Android Studio wyświetla klasy, które według niego wskazują wycieki pamięci w przypadku instancji ActivityFragment w Twojej aplikacji.

Aby ręcznie wyszukać wycieki pamięci, przejrzyj listy klas i instancji, aby znaleźć obiekty o dużym rozmiarze zachowanym. Wyszukaj wycieki pamięci spowodowane przez:

  • Długotrwałe odwołania do Activity lub Context, które mogą ujawniać wykres kompozycji hostowanego interfejsu Compose (np. ComposeView i jego kompozycje podrzędne).
  • Wyciekające obiekty stanu Jetpack Compose (MutableState), elementy przechowujące stan lub lambdy, które przechwytują Context.
  • Zapominanie o zwalnianiu miejsca po słuchaczach lub obserwatorach w bloku onDispose funkcji DisposableEffect.
  • Klasy wewnętrzne niestatyczne, np. a Runnable, które mogą zawierać instancję Activity.
  • pamięci podręczne, które przechowują obiekty dłużej niż jest to konieczne;

Gdy znajdziesz potencjalne wycieki pamięci, użyj kart PolaOdwołania w sekcji Szczegóły instancji, aby przejść do interesującej Cię instancji lub wiersza kodu źródłowego.

Wywoływanie wycieków pamięci na potrzeby testów

Aby przeanalizować wykorzystanie pamięci, obciąż kod aplikacji i spróbuj wymusić wycieki pamięci. Jednym ze sposobów wywołania wycieków pamięci w aplikacji jest pozostawienie jej na jakiś czas, a następnie sprawdzenie sterty. Wycieki mogą przedostawać się na górę przydziałów w stercie. Im mniejszy wyciek, tym dłużej musisz uruchamiać aplikację, aby go zobaczyć.

Wyciek pamięci możesz też wywołać na jeden z tych sposobów:

  • Obróć urządzenie z pozycji pionowej do poziomej i z powrotem kilka razy, gdy jest w różnych stanach aktywności. Obracanie urządzenia może często powodować wyciek pamięci w aplikacji, jeśli przechowuje ona odwołanie do Activity lub Context w operacjach asynchronicznych lub w obiektach przechowujących stan. W takim przypadku wycieka też Activity (a w konsekwencji drzewo interfejsu Compose hostowane przez ten obiekt i powiązane z nim drzewa stanu).
  • Przełączaj się między aplikacją a inną aplikacją w różnych stanach aktywności. Na przykład przejdź do ekranu głównego, a potem wróć do aplikacji.

Eksportowanie i importowanie nagrania zrzutu sterty

Możesz eksportować i importować plik zrzutu stosu na karcie Poprzednie nagrania w programie profilującym. Android Studio zapisuje nagranie jako plik .hprof.

Możesz też użyć innego analizatora plików .hprof, np. jhat. W tym celu musisz przekonwertować plik .hprof z formatu Androida na format pliku .hprof Java SE. Aby przekonwertować format pliku, użyj narzędzia hprof-conv dostępnego w katalogu {android_sdk}/platform-tools/. Uruchom polecenie hprof-conv z 2 argumentami: oryginalną nazwą pliku .hprof i lokalizacją, w której ma zostać zapisany przekonwertowany plik .hprof, w tym nową nazwą pliku .hprof. Przykład:

hprof-conv heap-original.hprof heap-converted.hprof

Dodatkowe materiały