Sobes.tech
Middle+

Wie erkennt man Speicherlecks bei der Analyse eines Dumps?

sobes.tech KI

Antwort von AI

Um die Speicherleckage in einem Dump (HPROF-Datei) zu erkennen, werden Werkzeuge verwendet, die den Objektgraphen im Heap analysieren. Hauptschritte:

  1. Speicher-Dump erstellen:

    • Über den Android Studio Memory Profiler.
    • Mit dem Befehl adb shell dumpheap <Paketname> /data/local/tmp/dump.hprof.
    • Über den Systemaufruf Debug.dumpHprofData(filePath).
  2. Dump analysieren:

    • Dump in Android Studio öffnen: im Memory Profiler oder über das Menü "Datei" -> "Öffnen".
    • Objekte analysieren: Objekte nach Größe (Shallow Size, Retained Size) und Anzahl sortieren.
    • Verdächtige Objekte suchen: Klassen, die zerstört werden sollten (z.B. Activity, Fragment, Contexts), aber viele Instanzen oder eine große Retained Size aufweisen.
    • Pfad zum Objekt untersuchen (Reference Chain): Wählen Sie ein verdächtiges Objekt aus und verfolgen Sie seinen Weg zu den Wurzel-Objekten (GC roots). Dies zeigt, wer die Referenz hält und die Garbage Collection verhindert.
    • Statische Referenzen suchen: Statische Felder sind oft eine Quelle für Lecks, wenn sie langlebige Referenzen auf Kontexte oder Views speichern.
    • LeakCanary verwenden: Die Bibliothek automatisiert die Erkennung, den Dump und die Analyse von Lecks in Echtzeit und liefert eine detaillierte Beschreibung des Leckpfads.
  3. Ergebnisinterpretation:

    • Ein langer Pfad zu GC root, der Referenzen auf Objekte enthält, die zerstört werden sollten, weist auf ein Problem hin.
    • Referenzen aus statischen Feldern, AsyncTask, Handlern mit Verzögerungen, nicht ordnungsgemäß abgemeldeten Listeners/Callbacks oder Singletons in Aktivitäten oder Views sind häufig Ursachen für Lecks.

Beispiel für die Analyse des Pfads zu GC root im Android Studio Memory Profiler:

// Beispiel für einen Pfad zu GC root, der auf ein Leck hinweist
// android.app.Activity-Instanz mit mDestroyed=true
//   Referenz auf android.widget.LinearLayout
//     Referenz auf android.view.View $ListenerInfo
//       Referenz auf com.example.MyActivity$1 (anonyme Klasse, die View.OnClickListener implementiert)
//         Referenz auf com.example.MyActivity (Leck verursachend)

In diesem Beispiel hält eine anonyme Klasse (Button-Klick-Listener) eine implizite Referenz auf MyActivity, obwohl die Aktivität bereits zerstört sein sollte (mDestroyed=true). Dieser Listener scheint von einem anderen langlebigen Objekt (z.B. statisches Feld oder Singleton) registriert oder gehalten zu werden.