Zrób zrzut sterty, aby sprawdzić, które obiekty w aplikacji zużywają pamięć w momencie zrzutu, i zidentyfikować wycieki pamięci lub zachowanie związane z alokacją pamięci które prowadzi do zacinania się, zawieszania, a nawet awarii aplikacji. Zrzuty sterty są szczególnie przydatne po dłuższej sesji użytkownika, gdy mogą pokazywać obiekty, które nadal znajdują się w pamięci, choć nie powinny.
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
wiersza poleceń za pomocą polecenia dumpsys oraz
zobaczyć 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, odśmiecacz zwalnia nieużywaną pamięć z powrotem do sterty. Sposób, w jaki Android znajduje nieużywaną pamięć, jest stale ulepszany, ale w pewnym momencie we wszystkich wersjach Androida system musi na chwilę wstrzymać Twój kod. W większości przypadków przerwy są niezauważalne. Jeśli jednak aplikacja przydziela pamięć szybciej, niż system może ją zbierać, aplikacja może się opóźniać, gdy odśmiecacz zwalnia wystarczającą ilość pamięci, aby zaspokoić alokacje. Opóźnienie może spowodować, że aplikacja będzie pomijać klatki i widocznie spowolnić działanie.
Nawet jeśli aplikacja nie wykazuje spowolnienia, może wyciekać pamięć i zachowywać ją nawet wtedy, gdy działa w tle. Takie zachowanie może spowolnić działanie pamięci w pozostałej części systemu, wymuszając niepotrzebne zdarzenia odśmiecania pamięci. W końcu system jest zmuszony do zamknięcia procesu aplikacji, aby odzyskać pamięć. Gdy użytkownik wróci do aplikacji, proces aplikacji musi zostać całkowicie uruchomiony ponownie.
Więcej informacji o praktykach programistycznych, które mogą zmniejszyć zużycie pamięci przez aplikację , znajdziesz w artykule Zarządzanie pamięcią aplikacji.
Omówienie zrzutu sterty
Aby przechwycić zrzut stosu, wybierz zadanie Analizuj wykorzystanie pamięci (zrzut stosu) (użyj Program profilujący: uruchom „app” jako z możliwością debugowania (pełne dane)), aby przechwycić zrzut stosu. Podczas zrzutu sterty ilość pamięci Javy może tymczasowo wzrosnąć. Jest to normalne, ponieważ zrzut sterty odbywa się w tym samym procesie co aplikacja i wymaga pewnej ilości pamięci do zebrania danych. Po zrobieniu zrzutu sterty zobaczysz te informacje:
Lista klas zawiera te informacje:
- Alokacje: liczba alokacji w stercie.
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 frameworka, takich jak
Bitmap.Rozmiar płytki: łączna ilość pamięci Javy używanej przez ten typ obiektu (w bajtach).
Rozmiar zachowany: łączny rozmiar pamięci zachowanej ze względu na wszystkie instancje tej klasy (w bajtach).
Użyj menu sterty, aby filtrować według określonych stert:
- Stos aplikacji (domyślnie): główny stos, na którym aplikacja przydziela pamięć.
- Stos obrazu: obraz rozruchowy systemu zawierający klasy, które są wstępnie ładowane podczas uruchamiania. Alokacje tutaj nigdy się nie przenoszą ani nie znikają.
- Stos Zygote: stos kopiowania przy zapisie, z którego w systemie Android rozwidla się proces aplikacji.
Użyj menu Uporządkuj, aby wybrać sposób uporządkowania alokacji:
- Uporządkuj według klasy (domyślnie): grupuje wszystkie alokacje na podstawie nazwy klasy.
- Uporządkuj według pakietu: grupuje wszystkie alokacje na podstawie nazwy pakietu.
Użyj menu klasy, aby filtrować według grup klas:
- Wszystkie klasy (domyślnie): pokazuje 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: pokazuje tylko klasy zdefiniowane przez Twój projekt.
Kliknij nazwę klasy, aby otworzyć panel Instancja. Każda wymieniona instancja zawiera te informacje:
- Głębokość: najkrótsza 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 i nowszym.
- Rozmiar płytki: rozmiar tej instancji w pamięci Javy.
- Rozmiar zachowany: rozmiar pamięci, którą 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 pierwotne typy danych
w Javie. Kliknij pole lub odwołanie prawym przyciskiem myszy, aby przejść do powiązanej instancji lub wiersza w kodzie źródłowym.
- Pola: pokazuje wszystkie pola w tej instancji.
- Odwołania: pokazuje wszystkie odwołania do obiektu wyróżnionego na karcie Instancja.
Wykrywanie zduplikowanych bitmap
Od Androida Studio Narwhal 4 możesz też wykrywać zbędne bitmapy w widoku Zrzut sterty.
Aby je znaleźć:
- Otwórz kartę Profiler w Android Studio.
- Kliknij Zrzut sterty (lub Analizuj zużycie pamięci) i kliknij nagraj, aby zrobić migawkę bieżącego stanu pamięci aplikacji.
- Przeskanuj wyniki analizy pod kątem żół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, wybrać Filtruj według: i wybrać ustawienie Zduplikowane bitmapy.
- Kliknij dowolny oznaczony wpis, aby otworzyć panel Podgląd bitmapy , który pozwala dokładnie zobaczyć, który obraz jest powtarzany.
- Użyj tego wizualnego potwierdzenia, aby znaleźć zbędną logikę ładowania w kodzie i wdrożyć lepszą strategię buforowania.
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
pokazuje klasy, które według niego wskazują na wycieki pamięci w przypadku
Activity i
Fragment instancji w aplikacji.
Aby ręcznie wyszukać wycieki pamięci, przejrzyj listy klas i instancji, aby znaleźć obiekty o dużym rozmiarze zachowanym. Szukaj wycieków pamięci spowodowanych przez jedną z tych przyczyn:
- Długotrwałe odwołania do
ActivitylubContext, które mogą powodować wyciek hostowanego wykresu kompozycji Compose (np.ComposeViewi jego podkompozycje). - Wyciek obiektów stanu Jetpack Compose (
MutableState), posiadaczy stanu lub lambd, które przechwytująContext. - Zapomnienie o wyczyszczeniu słuchaczy lub obserwatorów w bloku
onDisposeelementuDisposableEffect. - Niestatyczne klasy wewnętrzne, takie jak 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 Pola i Odwołania w sekcji Szczegóły instancji , aby przejść do instancji lub wiersza kodu źródłowego, który Cię interesuje.
Wywoływanie wycieków pamięci na potrzeby testowania
Aby analizować wykorzystanie pamięci, należy obciążyć kod aplikacji i spróbować wymusić wycieki pamięci. Jednym ze sposobów na wywołanie wycieków pamięci w aplikacji jest pozostawienie jej na jakiś czas przed sprawdzeniem sterty. Wycieki mogą przenikać do góry alokacji 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:
- Wielokrotnie obracaj urządzenie z orientacji pionowej do poziomej i z powrotem w różnych stanach aktywności. Obracanie urządzenia może często powodować wyciek
Activity(a w konsekwencji jego hostowanego drzewa interfejsu Compose i powiązanych drzew stanu), jeśli aplikacja zawiera odwołanie doActivitylubContextw operacjach asynchronicznych lub posiadaczach 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
Plik zrzutu sterty możesz
eksportować i importować
z karty Poprzednie nagrania w profilerze. 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 format pliku
.hprof Java SE. Aby przekonwertować format pliku, użyj narzędzia hprof-conv znajdującego się 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