Wykonaj zrzut stosu, aby sprawdzić, które obiekty w aplikacji zużywają pamięć w momencie wykonania zrzutu. Dzięki temu możesz zidentyfikować wycieki pamięci lub zachowanie przy przydzielaniu pamięci, które prowadzi do zacinania się, zawieszania i nawet wyłączania aplikacji. Jest to szczególnie przydatne po długiej sesji użytkownika, gdy mogą się pojawić obiekty, które nie powinny już znajdować się w pamięci.
Na tej stronie opisaliśmy narzędzia dostępne w Android Studio do zbierania i analizowania zrzutów stosu. Możesz też sprawdzić pamięć aplikacji z poziomu wiersza poleceń za pomocą dumpsys
oraz zobaczyć zdarzenia związane z zbieraniem pamięci (GC) w Logcat.
Dlaczego warto przeprowadzić profilowanie pamięci aplikacji
Android zapewnia sterowane środowisko zarządzania pamięcią – gdy system Android wykryje, że aplikacja nie używa już niektórych obiektów, zbieracz śmieci zwalnia nieużywaną pamięć z powrotem do stosu. Sposób, w jaki Android wyszukuje niewykorzystaną pamięć, jest stale ulepszany, ale w pewnym momencie w każdej wersji Androida system musi na krótko wstrzymać działanie kodu. W większości przypadków przerwy są niezauważalne. Jeśli jednak Twoja aplikacja przydziela pamięć szybciej niż system może ją zebrać, może się opóźnić, dopóki zbieracz nie zwolni wystarczającej ilości pamięci, aby zaspokoić Twoje potrzeby. Opóźnienie może spowodować pomijanie klatek przez aplikację i widoczne spowolnienie działania.
Nawet jeśli aplikacja nie działa wolno, to jeśli ma problem z wyciekiem pamięci, może zachować tę pamięć nawet wtedy, gdy działa w tle. Może to spowolnić wydajność pamięci w pozostałych częściach systemu, ponieważ spowoduje niepotrzebne zdarzenia zbierania śmieci. 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ć użycie pamięci przez aplikację, znajdziesz w artykule Zarządzanie pamięcią aplikacji.
Omówienie zrzutu stosu
Aby uzyskać zrzut stosu, wybierz zadanie Analiza wykorzystania pamięci (zrzut stosu) (użyj opcji Profilowanie: uruchom aplikację jako debuggowaną (pełne dane)), aby uzyskać zrzut stosu. Podczas zrzutu pamięci sterty może tymczasowo wzrosnąć ilość pamięci Java. To normalne, ponieważ zrzut stosu odbywa się w tym samym procesie co Twoja aplikacja i wymaga trochę pamięci na zebranie danych. Po utworzeniu kopii pamięci podręcznej zobaczysz:
Lista zajęć zawiera te informacje:
- Wydzielenia: liczba wydzielenia w pniu.
Rozmiar natywny: łączna ilość pamięci natywnej używanej przez ten typ obiektu (w bajtach). Tutaj zobaczysz pamięć niektórych obiektów przydzielonych w języku Java, ponieważ Android używa pamięci natywnej dla niektórych klas frameworka, takich jak
Bitmap
.Shallow Size (Płytka wielkość): łączna ilość pamięci Java używanej przez ten typ obiektu (w bajtach).
Zachowana wielkość: łączna wielkość pamięci zachowanej ze względu na wszystkie wystąpienia tej klasy (w bajtach).
W menu stosu możesz filtrować według określonych stosów:
- Stos aplikacji (domyślny): główny stos, na którym aplikacja przydziela pamięć.
- Stos obrazów: obraz rozruchu systemu zawierający klasy wstępnie wczytane podczas rozruchu. Przydziały nigdy się nie zmieniają ani nie znikają.
- Pamięć alokowana przez Zygote: pamięć alokowana na zapis, z której w systemie Androida wyodrębniany jest proces aplikacji.
Za pomocą menu układu wybierz sposób przypisywania budżetu:
- Uporządkuj według zajęć (domyślnie): wszystkie alokacje są grupowane według nazwy zajęć.
- Uporządkuj według pakietu: wszystkie alokacje są grupowane według nazwy pakietu.
Użyj menu zajęć, aby filtrować grupy zajęć:
- Wszystkie klasy (domyślnie): wyświetla wszystkie klasy, w tym te z bibliotek i zależności.
- Pokaż wycieki aktywności/fragmentów: pokazuje klasy, które powodują wycieki pamięci.
- Pokaż zajęcia projektu: wyświetla tylko zajęcia zdefiniowane przez Twój projekt.
Kliknij nazwę zajęć, aby otworzyć panel Instancja. Każda wymieniona instancja zawiera:
- 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 w Androidzie 7.0 lub nowszym.
- Shallow Size (płytki rozmiar): rozmiar tej instancji w pamięci Java.
- Zatrzymany rozmiar: rozmiar pamięci, w której ta instancja dominuje (zgodnie z drzewem dominatora).
Kliknij instancję, aby wyświetlić szczegóły instancji, w tym pola i odwołania. Typy pól i odwołań to w języku Java typy uporządkowane, tablice oraz proste typy danych. Kliknij prawym przyciskiem myszy pole lub odwołanie, aby przejść do powiązanego wystąpienia lub wiersza w kodzie źródłowym.
- Pola: zawiera wszystkie pola w tej instancji.
- Odwołania: zawiera wszystkie odwołania do obiektu wyróżnionego na karcie Instancja.
znajdowanie wycieków pamięci,
Aby szybko odfiltrować klasy, które mogą być powiązane z wyciekami pamięci, otwórz menu klasy i wybierz Pokaż wycieki aktywności/fragmentów. Android Studio wyświetla klasy, które według niego wskazują na wycieki pamięci w przypadku instancji Activity
i Fragment
w aplikacji. Typy danych wyświetlanych przez filtr to:
- instancje
Activity
, które zostały zniszczone, ale nadal są używane; Fragment
wystąpienia, które nie mają prawidłowegoFragmentManager
, ale są nadal używane.
Pamiętaj, że filtr może dać fałszywy alarm w tych sytuacjach:
Fragment
został utworzony, ale nie został jeszcze użyty.Fragment
jest przechowywane w pamięci podręcznej, ale nie w ramachFragmentTransaction
.
Aby ręcznie szukać wycieków pamięci, przejrzyj listy klas i wystąpieni, aby znaleźć obiekty o dużej wartości Zatrzymany rozmiar. Sprawdź, czy nie występują wycieki pamięci spowodowane przez:
- długotrwałe odwołania do obiektów
Activity
,Context
,View
,Drawable
oraz innych obiektów, które mogą zawierać odwołanie do konteneraActivity
lubContext
. - Niestatyczne klasy wewnętrzne, takie jak
Runnable
, które mogą zawierać instancjęActivity
. - pamięci podręczne, które przechowują obiekty dłużej niż to konieczne;
Gdy znajdziesz potencjalne wycieki pamięci, użyj kart Wielości i Odwołania na stronie Szczegóły instancji, aby przejść do interesującej Cię instancji lub linii kodu źródłowego.
Wywoływanie wycieków pamięci na potrzeby testowania
Aby przeanalizować wykorzystanie pamięci, należy obciążyć kod aplikacji i spróbować wymusić wycieki pamięci. Jednym ze sposobów wywołania wycieków pamięci w aplikacji jest pozostawienie jej na jakiś czas w stanie uruchomionym, zanim spróbujesz sprawdzić stos. Wycieki mogą się przenosić do góry alokacji w pniu. Im mniejszy wyciek, tym dłużej trzeba uruchamiać aplikację, aby go zobaczyć.
Wyciek pamięci możesz też wywołać na jeden z tych sposobów:
- Obróć urządzenie z poziomego na poziomy i z powrotem na poziomy kilka razy w różnych stanach aktywności. Obrócenie urządzenia często powoduje wyciek obiektu
Activity
,Context
lubView
, ponieważ system ponownie tworzy obiektActivity
, a jeśli aplikacja zawiera odwołanie do jednego z tych obiektów gdzie indziej, system nie może go usunąć. - przełączać się między aplikacjami w różnych stanach aktywności; Możesz na przykład przejść na ekran główny, a potem wrócić do aplikacji.
Eksportowanie i importowanie zapisu zrzutu stosu
Możesz eksportować i importować plik z zrzutem stosu na karcie Wcześniejsze nagrania w profilu. Android Studio zapisuje nagranie jako plik .hprof
.
Jeśli chcesz użyć innego analizatora plików .hprof
, np. jhat, musisz przekonwertować plik .hprof
z formatu Androida na plik .hprof
w formacie Java SE. Aby przekonwertować format pliku, użyj narzędzia hprof-conv
, które znajduje się w katalogu {android_sdk}/platform-tools/
. Uruchom polecenie hprof-conv
z 2 argumentami: pierwotną nazwą pliku .hprof
i lokalizacją, w której ma zostać zapisany przekonwertowany plik .hprof
, w tym nowa nazwa pliku .hprof
. Na przykład:
hprof-conv heap-original.hprof heap-converted.hprof