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 dort nicht mehr 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 analysieren sollten

Android bietet eine verwaltete Arbeitsspeicherumgebung. Wenn Android feststellt, dass Ihre App einige Objekte nicht mehr verwendet, gibt der Garbage Collector den nicht verwendeten Arbeitsspeicher wieder an den Heap zurück. Die Art und Weise, wie Android nicht verwendeten Arbeitsspeicher findet, wird ständig verbessert. Auf allen Android-Versionen muss das System jedoch Ihren Code kurz pausieren. Meistens sind die Pausen nicht wahrnehmbar. Wenn Ihre App jedoch Arbeitsspeicher schneller zuweist, als das System ihn erfassen kann, kann es zu Verzögerungen kommen, während der Garbage Collector genügend Arbeitsspeicher freigibt, um Ihre 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 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.

Übersicht über Heap-Dumps

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 etwas Arbeitsspeicher zum Erfassen der Daten 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:

  • Zuweisungen: 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 (Standard): 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.
  • Nach Paket anordnen: 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.
  • Aktivitäts-/Fragmentlecks anzeigen: Zeigt Klassen an, die Speicherlecks verursachen.
  • Projektklassen anzeigen: Zeigt nur Klassen an, 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 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 Verweise anzuzeigen. Häufige 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 wechseln.

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

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 Aktivitäts-/Fragmentlecks anzeigen aus. Android Studio zeigt Klassen an, die seiner Meinung nach 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 Retained Size. 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) lecken können.
  • Lecken von Jetpack Compose-Zustandsobjekten (MutableState), Zustandshaltern oder Lambdas, die Context erfassen.
  • Vergessen, Listener oder Observer 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 Verweise unter Instanzdetails , um zur Instanz oder Quellcodezeile zu springen.

Speicherlecks zum Testen 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 provozieren, 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. Das Drehen des Geräts kann oft dazu führen, dass eine App eine Activity (und damit die gehostete Compose-UI-Struktur und die zugehörigen Zustandsstrukturen) leckt, wenn Ihre App einen Verweis 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 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 auf dem Tab 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 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 für die konvertierte .hprof-Datei, einschließlich des neuen .hprof-Dateinamens. Beispiel:

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

Zusätzliche Ressourcen