Heap-Dump erfassen

Erstellen Sie einen Heap-Dump, um zu sehen, welche Objekte in Ihrer App zum Zeitpunkt der Erstellung Arbeitsspeicher belegen. So können Sie Speicherlecks oder ein Verhalten bei der Arbeitsspeicherzuweisung erkennen, das zu Ruckeln, Einfrieren und sogar App-Abstürzen führt. Es ist besonders hilfreich, Heap-Dumps nach einer längeren Nutzersitzung zu erstellen, da dann Objekte angezeigt werden können, die sich noch im Speicher befinden, aber nicht mehr dort sein sollten.

Auf dieser Seite werden die Tools beschrieben, die Android Studio zum Erfassen und Analysieren von Heap-Dumps bietet. Alternativ können Sie den Arbeitsspeicher Ihrer App über die Befehlszeile mit dumpsys prüfen und sich Garbage-Collection-Ereignisse (GC) in Logcat ansehen.

Warum Sie den Arbeitsspeicher Ihrer App profilieren sollten

Android bietet eine verwaltete Speicherumgebung. Wenn Android feststellt, dass Ihre App bestimmte Objekte nicht mehr verwendet, gibt die automatische Speicherbereinigung den nicht verwendeten Speicher wieder an den Heap frei. Die Art und Weise, wie Android ungenutzten Speicher findet, wird ständig verbessert. Bei allen Android-Versionen muss das System jedoch irgendwann den Code kurz pausieren. Meistens sind die Pausen nicht wahrnehmbar. Wenn Ihre Anwendung jedoch schneller Speicher zuweist, als das System ihn freigeben kann, kann es zu Verzögerungen kommen, während der Collector genügend Speicher freigibt, um die Zuweisungen zu erfüllen. Die Verzögerung kann dazu führen, dass Ihre App Frames überspringt und sichtbar langsamer wird.

Auch wenn Ihre App nicht langsam ist, kann sie, wenn sie Speicherlecks aufweist, diesen Speicher auch dann belegen, wenn sie im Hintergrund ausgeführt wird. Dieses Verhalten kann die Speicherleistung des restlichen Systems verlangsamen, da unnötige Speicherbereinigungsereignisse erzwungen werden. Schließlich muss das System den App-Prozess beenden, um den Arbeitsspeicher freizugeben. Wenn der Nutzer dann zu deiner App zurückkehrt, muss der App-Prozess vollständig neu gestartet werden.

Informationen zu Programmierpraktiken, mit denen Sie den Arbeitsspeicherverbrauch Ihrer App reduzieren können, finden Sie unter Arbeitsspeicher Ihrer App verwalten.

Heap-Dump – Übersicht

Wählen Sie die Aufgabe Arbeitsspeichernutzung analysieren (Heap-Dump) aus (verwenden Sie Profiler: „app“ als debugfähig ausführen (vollständige Daten)), um einen Heap-Dump zu erfassen. Während des Heap-Dumps kann sich die Menge des Java-Arbeitsspeichers vorübergehend erhöhen. Das ist normal, da der Heap-Dump im selben Prozess wie Ihre Anwendung erfolgt und etwas Arbeitsspeicher zum Erfassen der Daten benötigt. Nachdem Sie den Heap-Dump erfasst haben, sehen Sie Folgendes:

Die Heap-Dump-Ansicht im Android Studio Profiler

In der Liste der Kurse werden die folgenden Informationen angezeigt:

  • Zuweisungen: Anzahl der Zuweisungen im Heap.
  • Native Größe: Gesamtmenge des nativen Speichers, der von diesem Objekttyp verwendet wird (in Byte). Hier wird der Arbeitsspeicher für einige in Java zugewiesene Objekte angezeigt, da Android für einige Framework-Klassen wie Bitmap nativen Arbeitsspeicher verwendet.

  • Flache Größe: Gesamtmenge des von diesem Objekttyp verwendeten Java-Arbeitsspeichers (in Byte).

  • Beibehaltene Größe: Gesamtgröße des Arbeitsspeichers, der aufgrund aller Instanzen dieser Klasse beibehalten wird (in Byte).

Verwenden Sie das Heap-Menü, um nach bestimmten Heaps zu filtern:

  • App-Heap (Standard): Der primäre Heap, auf dem Ihre App Speicher zuweist.
  • Image-Heap: Das System-Boot-Image, das Klassen enthält, die während des Bootvorgangs vorab geladen werden. Zuweisungen werden hier nie verschoben oder entfernt.
  • Zygote-Heap: Der Copy-on-Write-Heap, von dem ein App-Prozess im Android-System abgespalten wird.

Wählen Sie im Drop-down-Menü „Anordnung“ aus, wie die Zuweisungen angeordnet werden sollen:

  • Nach Klasse anordnen (Standardeinstellung): Alle Zuweisungen werden nach Klassennamen gruppiert.
  • Nach Paket anordnen: Alle Zuweisungen werden nach Paketname gruppiert.

Über das Drop-down-Menü „Klasse“ können Sie nach Gruppen von Klassen filtern:

  • Alle Klassen (Standardeinstellung): Es werden alle Klassen angezeigt, einschließlich derer aus Bibliotheken und Abhängigkeiten.
  • Aktivitäts-/Fragmentlecks anzeigen: Zeigt Klassen an, die Speicherlecks verursachen.
  • Projektklassen anzeigen: Es werden nur Klassen angezeigt, die von Ihrem Projekt definiert wurden.

Klicken Sie auf einen Klassennamen, um den Bereich Instanz zu öffnen. Jede aufgeführte Instanz enthält Folgendes:

  • Tiefe: Die kürzeste Anzahl von Hops von einem beliebigen GC-Stamm zur ausgewählten Instanz.
  • Native Größe: Größe dieser Instanz im nativen Speicher. Diese Spalte ist nur für Android 7.0 und höher sichtbar.
  • Flache Größe: Größe dieser Instanz im Java-Arbeitsspeicher.
  • Beibehaltene Größe: Größe des Speichers, der von dieser Instanz dominiert wird (gemäß dem Dominatorbaum).

Klicken Sie auf eine Instanz, um die Instanzdetails einschließlich der Felder und Referenzen aufzurufen. Gängige Feld- und Referenztypen sind strukturierte Typen , Arrays und primitive Datentypen in Java. Klicken Sie mit der rechten Maustaste auf ein Feld oder einen Verweis, um zur zugehörigen Instanz oder Zeile im Quellcode zu gelangen.

  • Felder: Hier werden alle Felder in dieser Instanz angezeigt.
  • Verweise: Zeigt alle Verweise auf das Objekt an, das auf dem Tab Instanz hervorgehoben ist.
Die Ansichten Instanzen, Felder und Referenzen im Toolfenster „Heap Dump“.

Doppelte Bitmaps erkennen

Ab Android Studio Narwhal 4 können Sie redundante Bitmaps auch in der Heap-Dump-Ansicht erkennen.

So kannst du sie finden:

  1. Tab „Profiler“ in Android Studio öffnen
  2. Klicken Sie auf Heap-Dump (oder Arbeitsspeichernutzung analysieren) und dann auf „Aufzeichnen“, um einen Snapshot des aktuellen Arbeitsspeicherstatus Ihrer App zu erstellen.
  3. Suchen Sie in den Analyseergebnissen nach dem gelben Warndreieck ⚠️, mit dem Android Studio doppelte Bitmaps kennzeichnet, die mehrmals gespeichert werden.
    • Alternativ können Sie in der Kopfzeile des Profilers die Option Filtern nach: und dann die Einstellung Doppelte Bitmaps auswählen.
  4. Klicken Sie auf einen markierten Eintrag, um den Bereich Bitmap-Vorschau zu öffnen. Dort sehen Sie genau, welches Bild der wiederholte Verursacher ist.
  5. Verwenden Sie diese visuelle Bestätigung, um die redundante Ladelogik in Ihrem Code zu finden und eine bessere Caching-Strategie zu implementieren.
Suchen Sie nach doppelten Bitmaps, die mit dem gelben Warndreieck ⚠️ gekennzeichnet sind.

Speicherlecks finden

Wenn Sie schnell nach Klassen filtern möchten, die möglicherweise mit Speicherlecks in Verbindung stehen, öffnen Sie das Drop-down-Menü für Klassen und wählen Sie Aktivitäts-/Fragmentlecks anzeigen aus. Android Studio zeigt Klassen an, die auf Speicherlecks für Activity- und Fragment-Instanzen in Ihrer App hinweisen.

Wenn Sie manuell nach Speicherlecks suchen möchten, durchsuchen Sie die Klassen- und Instanzlisten nach Objekten mit einer großen beibehaltenen Größe. Suchen Sie nach Speicherlecks, die durch Folgendes verursacht werden:

  • Langlebige Verweise auf Activity oder Context, die den gehosteten Compose-Kompositionsgraphen (z. B. ComposeView und seine untergeordneten Composables) preisgeben können.
  • Leaking von Jetpack Compose-Zustandsobjekten (MutableState), Zustandshaltern oder Lambdas, die Context erfassen.
  • Vergessen, Listener oder Beobachter im onDispose-Block eines DisposableEffect zu bereinigen.
  • Nicht statische innere Klassen wie Runnable, die eine Activity-Instanz enthalten können.
  • Caches, die Objekte länger als nötig speichern.

Wenn Sie potenzielle Speicherlecks finden, können Sie die Tabs Felder und Referenzen unter Instanzdetails verwenden, um zur gewünschten Instanz oder Quellcodezeile zu springen.

Speicherlecks zu Testzwecken auslösen

Um die Speichernutzung zu analysieren, sollten Sie Ihren Anwendungscode einem Stresstest unterziehen und versuchen, Speicherlecks zu erzwingen. Eine Möglichkeit, Speicherlecks in Ihrer App zu provozieren, besteht darin, sie eine Weile laufen zu lassen, bevor Sie den Heap prüfen. Lecks können sich bis an die Spitze der Zuweisungen im Heap ausbreiten. Je kleiner das Leck ist, desto länger müssen Sie die App jedoch ausführen, um es zu sehen.

Sie können ein Speicherleck auch auf eine der folgenden Arten auslösen:

  • Drehe das Gerät mehrmals vom Hoch- ins Querformat und wieder zurück, während es sich in verschiedenen Aktivitätsstatus befindet. Wenn das Gerät gedreht wird, kann es oft zu einem Speicherleck bei einer Activity (und folglich auch bei der gehosteten Compose-UI-Struktur und den zugehörigen Zustandsstrukturen) kommen, wenn Ihre App einen Verweis auf die Activity oder Context in asynchronen Vorgängen oder State Holdern enthält.
  • Wechsle zwischen deiner App und einer anderen App, während sich die Apps in verschiedenen Aktivitätszuständen befinden. Rufen Sie beispielsweise den Startbildschirm auf und kehren Sie dann zu Ihrer App zurück.

Heap-Dump-Aufzeichnung exportieren und importieren

Sie können eine Heap-Dump-Datei über den Tab Frühere Aufzeichnungen im Profiler exportieren und importieren. Android Studio speichert die Aufzeichnung als .hprof-Datei.

Wenn Sie stattdessen einen anderen .hprof-Dateianalysator wie jhat verwenden möchten, müssen Sie die .hprof-Datei vom Android-Format in das Java SE-.hprof-Dateiformat konvertieren. Verwenden Sie zum Konvertieren des Dateiformats das Tool hprof-conv im Verzeichnis {android_sdk}/platform-tools/. Führen Sie den Befehl hprof-conv mit zwei Argumenten aus: dem ursprünglichen .hprof-Dateinamen und dem Speicherort, an den die konvertierte .hprof-Datei geschrieben werden soll, einschließlich des neuen .hprof-Dateinamens. Beispiel:

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

Zusätzliche Ressourcen