Heap-Dump erfassen

Erfassen Sie einen Heap-Dump, um zu sehen, welche Objekte in Ihrer App zum Zeitpunkt der Erfassung Arbeitsspeicher belegen, und um Speicherlecks oder ein Arbeitsspeicherzuweisungsverhalten zu identifizieren, das zu Ruckeln, Einfrieren und sogar zu App-Abstürzen führt. Es ist besonders hilfreich, Heap-Dumps nach einer längeren Nutzersitzung zu erstellen, da sie Objekte zeigen können, die sich noch im Arbeitsspeicher befinden, obwohl sie nicht mehr vorhanden 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 auch Ereignisse der automatischen Speicherbereinigung (GC) in Logcat sehen.

Warum Sie den Arbeitsspeicher Ihrer App profilieren sollten

Android bietet eine verwaltete Arbeitsspeicher umgebung. Wenn Android feststellt, dass Ihre App einige Objekte nicht mehr verwendet, gibt die Garbage Collection den nicht verwendeten Arbeitsspeicher wieder an den Heap zurück. Die Art und Weise, wie Android nicht verwendeten Arbeitsspeicher findet, wird ständig verbessert. Irgendwann muss das System jedoch bei allen Android-Versionen Ihren Code kurz pausieren. Meistens sind die Pausen nicht wahrnehmbar. Wenn Ihre App jedoch schneller Arbeitsspeicher zuweist, als das System ihn erfassen kann, kann es zu Verzögerungen kommen, während die Garbage Collection genügend Arbeitsspeicher freigibt, um Ihre Zuweisungen zu erfüllen. Die Verzögerung kann dazu führen, dass Ihre App Frames überspringt und sichtbar langsam ist.

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

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

Heap-Dump – Übersicht

Wählen Sie zum Erfassen eines Heap-Dumps die Aufgabe Analyze Memory Usage (Heap Dump) aus. Verwenden Sie dazu Profiler: run 'app' as debuggable (complete data). Während des Heap-Dumps kann die Menge an Java-Arbeitsspeicher vorübergehend ansteigen. Das ist normal, da der Heap-Dump im selben Prozess wie Ihre App erfolgt und zum Erfassen der Daten etwas Arbeitsspeicher benötigt. Nachdem Sie den Heap-Dump erfasst haben, sehen Sie Folgendes:

Die Ansicht „Heap-Dump“ im Android Studio Profiler.

Die Liste der Klassen enthält die folgenden Informationen:

  • Allocations: Anzahl der Zuweisungen im Heap.
  • Native Size: Gesamtmenge des nativen Arbeitsspeichers, der von diesem Objekttyp verwendet wird (in Byte). Hier sehen Sie Arbeitsspeicher für einige in Java zugewiesene Objekte, da Android nativen Arbeitsspeicher für einige Framework-Klassen wie Bitmap verwendet.

  • Shallow Size: Gesamtmenge des Java-Arbeitsspeichers, der von diesem Objekttyp verwendet wird (in Byte).

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

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

  • App heap (default): Der primäre Heap, auf dem Ihre App Arbeitsspeicher zuweist.
  • Image heap: Das System-Boot-Image mit Klassen, die während des Bootvorgangs vorab geladen werden. Zuweisungen hier werden nie verschoben oder entfernt.
  • Zygote heap: Der Copy-on-Write-Heap, aus dem ein App-Prozess in dem Android-System verzweigt wird.

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

  • Nach Klasse anordnen (Standard): Gruppiert alle Zuweisungen nach Klassennamen.
  • Arrange by package: Gruppiert alle Zuweisungen nach Paketnamen.

Verwenden Sie das Drop-down-Menü „Klasse“, um nach Gruppen von Klassen zu filtern:

  • Alle Klassen (Standard): Zeigt alle Klassen, einschließlich der Klassen aus Bibliotheken und Abhängigkeiten.
  • Show activity/fragment leaks: Zeigt Klassen, die Speicherlecks verursachen.
  • Show project classes: Zeigt nur Klassen, 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-Root zur ausgewählten Instanz.
  • Native Size: Größe dieser Instanz im nativen Arbeitsspeicher. Diese Spalte ist nur für Android 7.0 und höher sichtbar.
  • Shallow Size: Größe dieser Instanz im Java-Arbeitsspeicher.
  • Retained Size: Größe des Arbeitsspeichers, der von dieser Instanz dominiert wird (gemäß der Dominator-Struktur).

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

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

Doppelte Bitmaps erkennen

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

So finden Sie sie:

  1. Öffnen Sie in Android Studio den Tab „Profiler“.
  2. Klicken Sie auf Heap-Dump (oder Analyze Memory Usage) und dann auf „Aufzeichnen“, um einen Snapshot des aktuellen Arbeitsspeicherstatus Ihrer App zu erstellen.
  3. Suchen Sie in den Analyseergebnissen nach dem gelben Warnsymbol ⚠️. Android Studio verwendet es, um doppelte Bitmaps zu kennzeichnen, die mehrmals gespeichert werden.
    • Alternativ können Sie in der Profiler-Kopfzeile Filtern nach auswählen und dann die Einstellung Doppelte Bitmaps auswählen.
  4. Klicken Sie auf einen beliebigen gekennzeichneten Eintrag, um den Bereich Bitmap-Vorschau zu öffnen. So können Sie genau sehen, welches Bild mehrfach vorhanden ist.
  5. Mit dieser visuellen Bestätigung können Sie die redundante Ladelogik in Ihrem Code finden und eine bessere Caching-Strategie implementieren.
Suchen Sie mit dem gelben Warnsymbol ⚠️ nach doppelten Bitmaps.

Speicherlecks finden

Wenn Sie schnell nach Klassen filtern möchten, die möglicherweise mit Speicherlecks in Verbindung stehen, öffnen Sie das Drop-down-Menü „Klasse“ und wählen Sie Show activity/fragment leaks aus. Android Studio zeigt Klassen an, die seiner Meinung nach auf Speicherlecks für Activity und Fragment-Instanzen in Ihrer App hinweisen.

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

  • Langlebige Referenzen auf Activity oder Context, die das gehostete Compose Kompositionsdiagramm (z. B. ComposeView und seine untergeordneten Kompositionen) lecken können.
  • Lecks 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 enthalten.

Wenn Sie potenzielle Speicherlecks finden, verwenden Sie die Tabs Felder und Referenzen unter Instanzdetails , um zur Instanz oder Quellcodezeile zu springen.

Speicherlecks zu Testzwecken auslösen

Um die Arbeitsspeichernutzung zu analysieren, sollten Sie Ihren App-Code belasten und versuchen, Speicherlecks zu erzwingen. Eine Möglichkeit, Speicherlecks in Ihrer App zu verursachen, besteht darin, sie eine Weile auszuführen, bevor Sie den Heap prüfen. Lecks können bis an die Spitze der Zuweisungen im Heap gelangen. Je kleiner das Leck ist, desto länger müssen Sie die App ausführen, um es zu sehen.

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

  • Drehen Sie das Gerät mehrmals vom Hochformat ins Querformat und wieder zurück, während es sich in verschiedenen Aktivitätszuständen befindet. Durch das Drehen des Geräts kann es oft zu einem Leck einer Activity (und damit des gehosteten Compose-UI-Baums und der zugehörigen Zustandsbäume) kommen, wenn Ihre App eine Referenz auf die Activity oder Context in asynchronen Vorgängen oder Zustandshaltern enthält.
  • Wechseln Sie zwischen Ihrer App und einer anderen App, während sie sich in verschiedenen Aktivitätszuständen befindet. Gehen Sie beispielsweise zum Startbildschirm und kehren Sie dann zu Ihrer App zurück.

Heap-Dump-Aufzeichnung exportieren und importieren

Sie können eine Heap-Dump Datei auf dem Tab Past Recordings (Vergangene Aufzeichnungen) im Profiler exportieren und importieren. Android Studio speichert die Aufzeichnung als .hprof-Datei.

Wenn Sie alternativ einen anderen .hprof Datei-Analyzer wie jhat, verwenden möchten, müssen Sie die .hprof Datei vom Android-Format in das Java SE .hprof Datei-Format konvertieren. Verwenden Sie dazu 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 für die konvertierte .hprof-Datei, einschließlich des neuen .hprof-Dateinamens. Beispiel:

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

Zusätzliche Ressourcen