Heap-Dump erfassen

Erstellen Sie einen Heap-Dump, um zu sehen, welche Objekte in Ihrer App zum Zeitpunkt der Erfassung Speicher belegen, und Speicherlecks oder Speicherzuweisungsverhalten zu identifizieren, das zu Rucklern, Einfrieren und sogar App-Abstürzen führt. Es ist besonders hilfreich, Heap-Dumps nach einer längeren Nutzersitzung zu erstellen, wenn Objekte im Arbeitsspeicher angezeigt werden, die 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 App-Speicher über die Befehlszeile mit dumpsys prüfen und sich GC-Ereignisse (Garbage Collection) in Logcat ansehen.

Warum Sie den Arbeitsspeicher Ihrer App analysieren sollten

Android bietet eine verwaltete Speicherumgebung: Wenn Android feststellt, dass Ihre App einige Objekte nicht mehr verwendet, gibt der Garbage Collector den nicht verwendeten Arbeitsspeicher wieder an den Heap frei. Die Art und Weise, wie Android ungenutzten Arbeitsspeicher findet, wird ständig verbessert. Bei allen Android-Versionen muss der Code jedoch irgendwann kurz pausiert werden. In den meisten Fällen sind die Pausen nicht wahrnehmbar. Wenn Ihre App jedoch Arbeitsspeicher schneller zuweist, als das System ihn erfassen kann, kann es zu Verzögerungen bei Ihrer App kommen, während der Profiler 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 läuft, kann sie bei Speicherlecks Arbeitsspeicher belegen, auch wenn sie im Hintergrund ausgeführt wird. Dieses Verhalten kann die Arbeitsspeicherleistung des restlichen Systems beeinträchtigen, da unnötige Garbage-Collection-Ereignisse erzwungen werden. Letztendlich ist das System gezwungen, Ihren App-Prozess zu beenden, um den Arbeitsspeicher wieder 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 Speichernutzung Ihrer App reduzieren können, finden Sie unter Verwaltung Ihres App-Speichers.

Heap-Dumps – Übersicht

Wenn Sie einen Heap-Dump erfassen möchten, wählen Sie die Aufgabe Arbeitsspeichernutzung analysieren (Heap-Dump) aus. Verwenden Sie Profiler: „app“ als debuggbare Anwendung ausführen (vollständige Daten), um einen Heap-Dump zu erfassen. Während des Dumps des Heaps kann sich der Java-Speicher vorübergehend erhöhen. Das ist normal, da der Heap-Dump im selben Prozess wie Ihre App ausgeführt wird und für die Erhebung der Daten etwas Arbeitsspeicher benötigt. Nachdem Sie den Heap-Dump erfasst haben, sehen Sie Folgendes:

Die Kursliste enthält die folgenden Informationen:

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

  • Shallow Size: Die Gesamtmenge an Java-Speicher, die von diesem Objekttyp verwendet wird (in Byte).

  • Behaltene Größe: Die Gesamtgröße des Arbeitsspeichers, der aufgrund aller Instanzen dieser Klasse belegt ist (in Byte).

Über das Menü „Heap“ können Sie nach bestimmten Heaps filtern:

  • App-Heap (Standard): Der primäre Heap, dem Ihre App Arbeitsspeicher zuweist.
  • Image-Heap: Das System-Boot-Image mit Klassen, die während des Bootens vorab geladen werden. Zuweisungen hier werden nie verschoben oder entfernt.
  • Zygote-Heap: Der Copy-on-Write-Heap, von dem ein App-Prozess im Android-System forkt.

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

  • Nach Kurs sortieren (Standard): Alle Zuweisungen werden nach Kursnamen gruppiert.
  • Nach Paket sortieren: Hier werden alle Zuweisungen nach Paketnamen gruppiert.

Im Drop-down-Menü „Kurs“ können Sie nach Kursgruppen filtern:

  • Alle Klassen (Standard): Es werden alle Klassen angezeigt, einschließlich derjenigen aus Bibliotheken und Abhängigkeiten.
  • Aktivitäts-/Fragmentlecks anzeigen: Hier werden Klassen angezeigt, die zu Speicherlecks führen.
  • Projektklassen anzeigen: Hier 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 GC-Stammknoten zur ausgewählten Instanz.
  • Native Größe: 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-Speicher.
  • Behaltene Größe: Größe des Arbeitsspeichers, den diese Instanz dominiert (gemäß dem Dominator-Baum).

Klicken Sie auf eine Instanz, um die Instanzdetails einschließlich der Felder und Verweise 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 eine Referenz, um die zugehörige Instanz oder Zeile im Quellcode aufzurufen.

  • Felder: Hier werden alle Felder in dieser Instanz angezeigt.
  • Referenzen: Hier werden alle Verweise auf das Objekt angezeigt, das auf dem Tab Instanz markiert ist.

Speicherlecks finden

Wenn Sie schnell nach Klassen filtern möchten, die mit Speicherlecks in Verbindung stehen könnten, öffnen Sie das Drop-down-Menü für Klassen 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. Zu den Datentypen, die der Filter anzeigt, gehören:

  • Activity-Instanzen, die gelöscht wurden, aber weiterhin referenziert werden.
  • Fragment-Instanzen, die keine gültige FragmentManager haben, aber trotzdem referenziert werden.

Beachten Sie, dass der Filter in den folgenden Fällen zu Falsch-Positiv-Ergebnissen führen kann:

  • Eine Fragment wurde erstellt, aber noch nicht verwendet.
  • Ein Fragment wird im Cache gespeichert, aber nicht als Teil einer FragmentTransaction.

Wenn Sie manuell nach Speicherlecks suchen möchten, können Sie in den Klassen- und Instanzlisten nach Objekten mit einer großen Retained Size suchen. Suchen Sie nach Speicherlecks, die durch eine der folgenden Ursachen verursacht wurden:

  • Langlebige Verweise auf Activity, Context, View, Drawable und andere Objekte, die eine Referenz auf den Activity- oder Context-Container enthalten könnten.
  • Nicht statische innere Klassen wie Runnable, die eine Activity-Instanz enthalten können.
  • Caches, in denen Objekte länger als nötig gespeichert werden

Wenn Sie potenzielle Speicherlecks finden, können Sie auf den Tabs Felder und Verweise unter Instanzdetails zur gewünschten Instanz- oder Quellcodezeile springen.

Speicherlecks für Tests auslösen

Um die Speichernutzung 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 laufen zu lassen, bevor Sie den Heap prüfen. Lecks können bis an die Spitze der Zuweisungen im Heap gelangen. Je kleiner der Leck ist, desto länger müssen Sie die App ausführen, um ihn zu sehen.

Sie können ein Speicherleck auch auf folgende Arten auslösen:

  • Drehen Sie das Gerät mehrmals zwischen Hoch- und Querformat, während sich das Gerät in verschiedenen Aktivitätsstatus befindet. Wenn Sie das Gerät drehen, kann das häufig dazu führen, dass eine App ein Activity-, Context- oder View-Objekt freigibt, da das System das Activity neu erstellt. Wenn Ihre App an anderer Stelle eine Referenz auf eines dieser Objekte enthält, kann das System es nicht durch die Garbage Collection bereinigen.
  • Zwischen Ihrer App und einer anderen App wechseln, während Sie sich in verschiedenen Aktivitätsstatus befinden. Rufen Sie beispielsweise den Startbildschirm auf und kehren Sie dann zur App zurück.

Heap-Dump-Aufzeichnung exportieren und importieren

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

Wenn Sie einen anderen .hprof-Dateien-Analysator wie jhat verwenden möchten, müssen Sie die .hprof-Datei aus dem Android-Format in das Java SE-.hprof-Dateiformat konvertieren. Verwenden Sie zum Konvertieren des Dateiformats das hprof-conv-Tool 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 dem die konvertierte .hprof-Datei mit dem neuen .hprof-Dateinamen gespeichert werden soll. Beispiel:

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