Heap Dump (Haldendump) ist eine Momentaufnahme des dynamischen Speichers einer Anwendung, die vollständige Informationen über alle lebenden Objekte enthält: ihre Klassen, Größen, gegenseitigen Referenzen und Erreichbarkeit von GC-Wurzeln. Heap Dump ist das primäre Werkzeug zur Analyse von Speicherlecks und Optimierung des Ressourcenverbrauchs. Laut Android Developers kann die Heap-Dump-Analyse bis zu 95% der Speicherlecks erkennen, einschließlich zyklischer Referenzen, vergessener Listener und nicht freigegebener statischer Referenzen.
Wichtige Erkenntnisse
Heap-Dump ist ein vollständiger Dump des Heaps der virtuellen Maschine — der Speicherbereich, in dem sich alle dynamisch erstellten Objekte befinden. In Java und Kotlin ist es der Dalvik/ART-Heap auf Android, in Swift und Objective-C der ARC-verwaltete Heap auf iOS. Ein Heap-Dump erfasst jedes Objekt, seine Klasse, Größe, Felder, Referenzen auf andere Objekte und Erreichbarkeitsflags von GC-Wurzeln (Stapelvariablen, statische Felder, JNI-Referenzen).
Der Hauptzweck eines Heap-Dumps ist die Erkennung von Speicherlecks. Ein Leck tritt auf, wenn eine Anwendung weiterhin Referenzen auf Objekte hält, die nicht mehr benötigt werden, und so deren Sammlung durch den Garbage Collector verhindert. Typische Ursachen: Ereignis-Listener, die beim Zerstören einer Activity nicht abgemeldet wurden; Singletons mit Referenzen auf Kontext; Closures, die self erfassen; statische Sammlungen, in die Daten ohne Entfernung hinzugefügt werden. Ein Heap-Dump liefert ein genaues Bild: welche Objekte „leben“, welche unnötig sind und wer genau sie referenziert.
Laut Google I/O stehen mehr als 60% der Crash-Berichte von Android-Apps im Zusammenhang mit OutOfMemoryError, und in 80% der Fälle ist die Ursache ein Speicherleck, das durch einen Heap-Dump erkennbar ist. Bei iOS-Apps ist die Situation ähnlich: Lecks aufgrund von Retain Cycles sind eine der häufigsten Crash-Ursachen, die durch das Allocations-Instrument in Xcode identifiziert werden.
Ein Heap-Dump sollte bei folgenden Symptomen durchgeführt werden: Die App verbraucht bei wiederholten Aktionen (Hin- und Hernavigieren zwischen Bildschirmen) linear Speicher; nach dem Schließen eines Bildschirms kehrt der Speicher nicht auf das Ausgangsniveau zurück; es treten OutOfMemoryError oder Speicherwarnungen unter iOS auf; die App wird aufgrund von Speicherüberschreitung beendet. Die regelmäßige Erfassung von Heap-Dumps ist Teil des Engineering-Kulturprotokolls in großen Mobilprojekten wie Instagram und Spotify.
Android Studio bietet den Memory Profiler — ein integriertes Werkzeug zur Erfassung von Heap-Dumps in Echtzeit. Zugänglich über View → Tool Windows → Profiler. Nach dem Starten der App wählen Sie die Sitzung aus, gehen Sie zum Tab Memory und klicken Sie auf Dump Java Heap. Android Studio pausiert die App, führt einen ART-Heap-Dump durch und lädt das Ergebnis zur Analyse. Die Dump-Datei hat das Format .hprof — der HPROF-Standard, der mit den meisten Speicheranalysetools kompatibel ist.
Nach dem Laden des Dumps zeigt Android Studio eine Objekttabelle mit Spalten an: Allocations (Anzahl der Instanzen), Native Size (Speicher außerhalb des ART-Heaps), Shallow Size (Speicher des Objekts selbst), Retained Size (Speicher des Objekts einschließlich seines gesamten Subgraphen). Das Filtern nach Klassennamen, Sortieren nach Retained Size und Suchen nach Paketen ermöglicht es, problematische Bereiche schnell zu finden.
// Typisches Leck — ein Listener, der in onDestroy nicht abgemeldet wurde
class MainActivity : AppCompatActivity() {
private val sensorManager by lazy {
getSystemService(SENSOR_SERVICE) as SensorManager
}
private val listener = MySensorListener()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sensorManager.registerListener(listener,
sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onDestroy() {
super.onDestroy()
// ❌ sensorManager.unregisterListener(listener) fehlt
// → Activity wird nicht vom GC erfasst, Heap-Dump zeigt das Leck
}
}
Der Tab Dominator Tree zeigt Objekte an, die die meiste Speicher halten. Wenn ein Objekt aus dem Dominator Tree entfernt wird, wird der gesamte von ihm gehaltene Speicher für die Garbage Collection verfügbar. Dies ist ein Schlüsselwerkzeug: Statt Tausende von Objekten zu durchsuchen, konzentrieren Sie sich auf 10–20, die 80–90% des Speichers kontrollieren. Laut Google ist die Dominator-Tree-Analyse der effektivste Weg, einen Leckpunkt zu finden, und reduziert die Analysezeit von Stunden auf Minuten.
Xcode Instruments bietet zwei Werkzeuge für die Arbeit mit Heap-Dumps: Allocations — Erfassung von Heap-Dumps mit Echtzeit-Verbrauchsdiagramm; Leaks — automatische Suche nach Lecks durch Retain-Cycle-Analyse. Allocations zeigt alle Objekte im Heap, ihre Größe, Anzahl der Erstellungen (Allocations) und Freigaben (Deallocations). Die Differenz zwischen Erstellungs- und Freigabeanzahl für eine bestimmte Klasse weist auf ein potenzielles Leck hin.
Die Erfassung eines Heap-Dumps in Allocations erfolgt über die Schaltfläche Snapshot Memory — das Werkzeug pausiert die App und erstellt einen vollständigen Dump. Danach stehen die Standardansichten zur Verfügung: Objektliste nach Klasse, Call Tree für jedes Objekt und ein Berichtsgenerator. Im Gegensatz zu Android Studio verwendet Xcode nicht .hprof, sondern speichert Daten in seinem eigenen .trace-Format, das mit Instruments kompatibel ist.
// Typisches iOS-Leck — Retain Cycle durch einen Closure
class NetworkManager {
var onComplete: ((Data) -> Void)?
func startRequest() {
// ❌ Closure erfasst self — Retain Cycle
onComplete = { data in
self.process(data)
}
}
func process(_ data: Data) {}
}
Das Leaks-Instrument erkennt automatisch Retain Cycles und Lecks durch Referenzgraph-Analyse. Es markiert leckende Objekte mit einem violetten Symbol und zeigt den Pfad zur Wurzel (GC Root). Zur Beseitigung eines Retain Cycles reicht es aus, [weak self] oder [unowned self] im Closure-Capture hinzuzufügen. Die regelmäßige Ausführung des Leaks-Instruments ist ein obligatorischer CI-Pipeline-Schritt in Teams, die Swift für die iOS-Entwicklung verwenden.
// Behebung — schwache Referenz auf self
onComplete = { [weak self] data in
guard let self else { return }
self.process(data)
}
Für eine korrekte Heap-Dump-Analyse müssen drei Schlüsselkennzahlen verstanden werden. Shallow Size ist die Speichermenge, die direkt vom Objekt belegt wird: seine Felder, Header und Ausrichtung. Für ein typisches Java/Kotlin-Objekt beträgt die Shallow Size 16–40 Bytes. Retained Size ist die Shallow Size des Objekts plus die gesamte Shallow Size aller Objekte, die nur über dieses Objekt erreichbar sind (d.h. bei seiner Entfernung zu Müll würden). Die Retained Size zeigt die tatsächliche Auswirkung des Objekts auf den Speicherverbrauch.
| Kennzahl | Beschreibung | Beispiel |
|---|---|---|
| Shallow Size | Größe des Objekts selbst in Bytes | Bitmap (100×100) = 40.016 B |
| Retained Size | Shallow Size + alles, was es hält | Activity mit View Tree = 2–5 MB |
| Deep Size | Retained Size + verschachtelte Objekte aus anderen Graphen | ScrollView mit Adapter = 10–50 MB |
Dominator Tree ist eine Struktur, in der jedes Objekt seinen „Dominator“ referenziert — das Objekt, das seine Erreichbarkeit kontrolliert. Wenn der Dominator entfernt wird, werden alle Objekte seines Unterbaums zu Müll. Die Dominator-Tree-Analyse ist der schnellste Weg, um herauszufinden, welches Objekt den meisten Speicher hält. Laut Eclipse MAT werden 90% der Lecks durch Überprüfung der Top-20 des Dominator Tree in 5 Minuten erkannt.
Der Prozess der Leckanalyse mittels Heap-Dump besteht aus mehreren Schritten. Schritt 1: Führen Sie die Aktion aus, die Speicher freigeben soll (schließen Sie den Bildschirm, beenden Sie den Vorgang). Schritt 2: Rufen Sie GC auf und erstellen Sie einen Heap-Dump. Schritt 3: Finden Sie Objekte, die hätten zerstört werden sollen. Schritt 4: Führen Sie für das verdächtige Objekt Path to GC Roots aus — die Referenzkette, die das Objekt am Leben hält. Die letzte Referenz in der Kette ist die Leckursache.
Die Funktion Path to GC Roots ist in Android Studio Profiler, Eclipse MAT und Xcode Instruments verfügbar. Sie zeigt die kürzeste Referenzkette von einer GC-Wurzel zum problematischen Objekt. Durch Ausschluss von schwachen (Weak) und weichen (Soft) Referenzen erhalten Sie nur die starken (Strong) — jene, die tatsächlich die Sammlung verhindern. Laut Square Engineering werden 70% der Lecks in Android-Apps durch nur zwei Muster verursacht: statische Referenzen auf Activity oder Context und registrierte, aber nicht abgemeldete Listener.
// Beispiel eines Lecks durch eine statische Referenz
object AppCache {
private val cache = mutableMapOf<String, Any>()
fun storeActivityReference(activity: Activity) {
cache["current_activity"] = activity // ❌ Leck!
}
}
// Behebung: schwache Referenz
object AppCacheFixed {
private val cache = mutableMapOf<String, WeakReference<Any>>()
}
Die Technik des Vergleichsmodus ist eine der effektivsten Methoden zur Leckerkennung. Erstellen Sie einen Heap-Dump vor und nach einer wiederholten Aktion. Vergleichen Sie die Instanzanzahlen der Schlüsselklassen: Wenn die Anzahl der Activity gestiegen ist, obwohl alle Aktivitäten geschlossen wurden — ist es ein Leck. Android Studio und Eclipse MAT unterstützen den automatischen Dump-Vergleich mit Hervorhebung von Unterschieden. Laut Google ermöglicht der Dump-Vergleich das Auffinden von Lecks, die bei einer Einzelanalyse unsichtbar sind, durch Akkumulationseffekt.
Basierend auf der Heap-Dump-Analyse in realen Projekten wurden bewährte Speicheroptimierungspraktiken entwickelt. Verwenden Sie WeakReference für Caches, Callbacks und Kontextreferenzen in langlebigen Objekten. Melden Sie Listener ab in onPause/onDestroy für Android und deinit für iOS. Vermeiden Sie große statische Sammlungen — wenn nötig, verwenden Sie LruCache mit Größenbeschränkung. Optimieren Sie Bitmaps: Laden Sie Bilder mit dem richtigen inSampleSize, verwenden Sie Glide oder Picasso mit Festplatten-Cache.
Integrieren Sie die regelmäßige Heap-Dump-Erfassung in Ihre CI-Pipeline. Richten Sie eine Aufgabe ein, die instrumentierte UI-Tests ausführt, wichtige Benutzerszenarien durchführt und den Heap-Dump mit einer Basislinie vergleicht. Wenn die Retained Size um mehr als 5% gegenüber der Basislinie steigt, wird der Build als Regression markiert. Dieser Ansatz wird bei Airbnb, Uber und anderen Unternehmen mit hohen Qualitätsanforderungen praktiziert. Laut Uber Engineering reduzierte die Implementierung der automatischen Heap-Dump-Analyse in CI speicherbezogene Fehler in einem Quartal um 70%.
// Beispiel einer Gradle-Aufgabe für automatischen Heap-Dump in CI
task profileMemory(type: Exec) {
commandLine 'adb', 'shell',
'am start -n com.example/.MainActivity'
// Warten auf Laden
doLast {
exec { commandLine 'adb', 'shell',
'am broadcast -a com.example.DUMP_HEAP' }
}
}
Häufig gestellte Fragen
Shallow Size ist die Größe des Objekts selbst (Felder + Header). Retained Size ist die Größe des Objekts plus aller Objekte, die bei seiner Entfernung zu Müll würden. Die Retained Size ist der Hauptindikator für die Auswirkung eines Objekts auf den Speicherverbrauch.
Über den Android Studio Profiler wählen Sie Gerät und Prozess aus, klicken auf Dump Java Heap. Alternativ über die Befehlszeile: adb shell am dumpheap PID /sdcard/dump.hprof, dann adb pull.
Ein Heap-Dump enthält alle lebenden Objekte. Wenn die App Caches, Bitmaps oder große Datenmengen verwendet, kann der Dump hunderte Megabyte erreichen. Filtern Sie nach Klassen oder verwenden Sie Eclipse MAT, um nur den Index zu laden.
Ja, verwenden Sie Eclipse MAT (Memory Analyzer Tool) — ein kostenloses Werkzeug zur Analyse von .hprof-Dateien. Es unterstützt Dominator Tree, Path to GC Roots, Dump-Vergleich und automatische Leckerkennung über den Leak Suspects Report.
Der Dump selbst — ja, weil die Dump-Erfassung alle Threads anhält (Stop-the-World). Ohne Dump — nein. Erstellen Sie Dumps in kontrollierten Umgebungen (Testumgebung, CI), nicht in der Produktion.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch