Heap Dump: wat is het, heap-analyse en het oplossen van geheugenlekken

Auteur: IT Sectr Gepubliceerd: 2026-05-07 Leestijd: 10 min

Heap Dump (heap-dump) — een momentopname van het dynamische geheugen van een applicatie met volledige informatie over alle levende objecten: hun klassen, groottes, onderlinge verwijzingen en bereikbaarheid vanaf root-knooppunten (GC roots). Heap Dump is het belangrijkste hulpmiddel voor het analyseren van geheugenlekken en het optimaliseren van resourcegebruik. Volgens Android Developers kan analyse van heap dumps tot 95% van de geheugenlekken opsporen, waaronder cyclische verwijzingen, vergeten listeners en niet-vrijgegeven statische verwijzingen.

Belangrijkste punten

  • Heap Dump — een momentopname van het volledige dynamische geheugen van een app met informatie over elk object en de verwijzingen ertussen.
  • Android Studio Memory Profiler maakt het mogelijk om heap dumps in realtime vast te leggen voor Java- en Kotlin-apps.
  • Xcode Instruments biedt de tool Allocations voor het maken en analyseren van heap dumps op iOS/macOS.
  • Shallow en retained size zijn de belangrijkste metrieken: shallow is de grootte van het object zelf, retained is de grootte van het object plus alle objecten die het vasthoudt.
  • Analyse van een heap dump omvat het zoeken naar de dominator tree, de grootste retained objects en de kortste paden naar GC roots.

Wat is een heap dump en waarom is het nodig

Heap dump is een volledige dump van de heap van de virtuele machine — het geheugengebied waar alle dynamisch gemaakte objecten worden geplaatst. In Java en Kotlin is dit Dalvik/ART op Android, in Swift en Objective-C — de door ARC beheerde heap op iOS. Een heap dump registreert elk object, zijn klasse, grootte, velden, verwijzingen naar andere objecten en vlaggen voor bereikbaarheid vanaf GC roots (stackvariabelen, statische velden, JNI-verwijzingen).

Het hoofddoel van een heap dump is het opsporen van geheugenlekken. Een lek ontstaat wanneer een applicatie verwijzingen blijft vasthouden naar objecten die niet langer nodig zijn, waardoor ze niet door de garbage collector (of ARC) kunnen worden opgeruimd. Typische oorzaken: event listeners die niet zijn afgemeld bij het vernietigen van een activity; singletons met verwijzingen naar context; closures die self vastpakken; statische collecties waar gegevens aan worden toegevoegd zonder ze te verwijderen. Een heap dump geeft een nauwkeurig beeld: welke objecten zijn „levend", welke zijn overbodig en wie precies verwijst ernaar.

Volgens Google I/O is meer dan 60% van de crashmeldingen van Android-apps gerelateerd aan OutOfMemoryError, en in 80% van de gevallen is de hoofdoorzaak een geheugenlek dat via een heap dump kan worden opgespoord. Voor iOS-apps is de situatie vergelijkbaar: lekken door retain cycles zijn een veelvoorkomende oorzaak van crashes die worden gedetecteerd via de Allocations-instrument in Xcode.

Wanneer is een heap dump nodig

Een heap dump moet worden uitgevoerd bij de volgende symptomen: de app verbruikt lineair geheugen bij herhaalde acties (heen en weer navigeren tussen schermen); na het sluiten van een scherm keert het geheugen niet terug naar het oorspronkelijke niveau; er treden OutOfMemoryError of memory warning-meldingen op iOS op; de app wordt beëindigd vanwege overschrijding van de geheugenlimiet (EXC_RESOURCE_RESOURCE op iOS). Regelmatig verzamelen van heap dumps maakt deel uit van de engineeringcultuur in grote mobiele projecten zoals Instagram en Spotify.

Heap dump in Android Studio: verkrijgen en analyseren

Android Studio biedt Memory Profiler — een ingebouwde tool voor het vastleggen van heap dumps in realtime. Bereikbaar via View → Tool Windows → Profiler. Start de app, selecteer de sessie, ga naar het tabblad Memory en klik op Dump Java Heap. Android Studio onderbreekt de app, voert een dump van de ART-heap uit en laadt het resultaat voor analyse. Het dumpbestand heeft de indeling .hprof — de HPROF-standaard die compatibel is met de meeste geheugenanalyzers.

Na het laden van de dump toont Android Studio een tabel met objecten met kolommen: Allocations (aantal instanties), Native Size (geheugen buiten de ART-heap), Shallow Size (geheugen van het object zelf), Retained Size (geheugen van het object met de hele subgraph). Filteren op klassenaam, sorteren op retained size en zoeken op pakketten maken het mogelijk om snel probleemgebieden te vinden.

kotlin
// Typisch lek — listener niet afgemeld in onDestroy
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) overgeslagen
        // → Activity wordt niet door GC verzameld, heap dump toont lek
    }
}

Dominator tree-analyse in Android Studio

Het tabblad Dominator Tree toont objecten die de meeste geheugen vasthouden. Als een object uit de dominator tree wordt verwijderd, wordt al het geheugen dat het vasthield beschikbaar voor verzameling. Dit is de belangrijkste tool: in plaats van duizenden objecten te bekijken, concentreer je je op 10-20 objecten die 80-90% van het geheugen beheren. Volgens Google is dominator tree-analyse de meest effectieve manier om een lekpunt te vinden, waardoor de analysetijd wordt teruggebracht van uren naar minuten.

Heap dump in Xcode Instruments: Allocations en Leaks

Xcode Instruments biedt twee tools voor het werken met heap dumps: Allocations — het vastleggen van een heap dump met een realtime verbruiksgrafiek; Leaks — het automatisch zoeken naar lekken via analyse van retain cycles. Allocations toont alle objecten in de heap, hun grootte, aantal aanmakingen (allocations) en vrijmakingen (deallocations). Het verschil tussen het aantal aanmakingen en vrijmakingen voor een specifieke klasse wijst op een potentieel lek.

Het vastleggen van een heap dump in Allocations gebeurt met de knop Snapshot Memory — de tool onderbreekt de app en maakt een volledige dump. Daarna zijn de standaardweergaven beschikbaar: een lijst van objecten per klasse, een call tree voor elk object en een rapportgenerator. In tegenstelling tot Android Studio gebruikt Xcode geen .hprof, maar slaat het gegevens op in het eigen formaat .trace, compatibel met Instruments.

swift
// Typisch iOS-lek — retain cycle via closure
class NetworkManager {
    var onComplete: ((Data) -> Void)?

    func startRequest() {
        // ❌ Closure pakt self vast — retain cycle
        onComplete = { data in
            self.process(data)
        }
    }
    func process(_ data: Data) {}
}

De Leaks-instrument detecteert automatisch retain cycles en lekken via analyse van de referentiegraaf. Het markeert lekkende objecten met een paars pictogram en toont het pad naar de root (GC root). Om een retain cycle te verhelpen, volstaat het om [weak self] of [unowned self] aan de closure toe te voegen. Regelmatig uitvoeren van de Leaks-instrument is een verplichte CI-stap in teams die Swift gebruiken voor iOS-ontwikkeling.

swift
// Oplossing — zwakke verwijzing naar self
onComplete = { [weak self] data in
    guard let self else { return }
    self.process(data)
}

Shallow size, retained size en dominator tree

Voor een correcte analyse van een heap dump moet u drie belangrijke metrieken begrijpen. Shallow size — de hoeveelheid geheugen die rechtstreeks door een object wordt ingenomen: de velden, header en uitlijning. Voor een typisch Java/Kotlin-object is de shallow size 16-40 bytes. Retained size — de shallow size van het object plus de totale shallow size van alle objecten die alleen via dit object bereikbaar zijn (dus afval worden bij verwijdering). Het is de retained size die de werkelijke impact van een object op het geheugenverbruik laat zien.

MetriekBeschrijvingVoorbeeld
Shallow sizeGrootte van het object zelf in bytesBitmap (100×100) = 40 016 B
Retained sizeShallow size + alles wat het vasthoudtActivity met View Tree = 2-5 MB
Deep sizeRetained size + geneste objecten uit andere grafenScrollView met adapter = 10-50 MB

Dominator tree — een structuur waarin elk object verwijst naar zijn „dominator" — het object dat zijn bereikbaarheid controleert. Als de dominator wordt verwijderd, worden alle objecten in zijn subboom afval. Dominator tree-analyse is de snelste manier om het object te vinden dat het meeste geheugen vasthoudt. Volgens Eclipse MAT (Memory Analyzer Tool) wordt 90% van de lekken opgespoord door de top-20 dominator tree in 5 minuten te bekijken.

Geheugenlekanalyse via heap dump

Het proces van lekanalyse via een heap dump bestaat uit verschillende stappen. Stap 1: voer de actie uit die het geheugen zou moeten vrijmaken (sluit het scherm, voltooi de bewerking). Stap 2: roep GC aan (System.gc() in Android, geforceerde snapshot in Xcode) en maak een heap dump. Stap 3: vind objecten die vernietigd hadden moeten zijn (bijv. een Activity-instantie na finish). Stap 4: voer voor het verdachte object Path to GC Roots uit — de keten van verwijzingen die het object levend houdt. De laatste verwijzing in de keten is de oorzaak van het lek.

Pad naar GC Roots (Path to GC Roots)

De functie Path to GC Roots is beschikbaar in Android Studio Profiler, Eclipse MAT en Xcode Instruments. Het toont de kortste keten van verwijzingen van GC root naar het problematische object. Door zwakke (weak) en zachte (soft) verwijzingen uit te sluiten, krijgt u alleen sterke (strong) verwijzingen — degenen die daadwerkelijk verzameling verhinderen. Volgens de statistieken van Square Engineering wordt 70% van de lekken in Android-apps veroorzaakt door slechts twee patronen: statische verwijzingen naar Activity of Context en geregistreerde maar niet afgemelde listeners.

kotlin
// Voorbeeld van lek via statische verwijzing
object AppCache {
    private val cache = mutableMapOf<String, Any>()

    fun storeActivityReference(activity: Activity) {
        cache["current_activity"] = activity // ❌ Lek!
    }
}

// Oplossing: zwakke verwijzing
object AppCacheFixed {
    private val cache = mutableMapOf<String, WeakReference<Any>>()
}

Twee heap dumps vergelijken

De techniek comparison mode — een van de meest effectieve methoden om lekken te vinden. Maak een heap dump voor en na een herhaalde actie (bijv. vijf keer naar een scherm navigeren en terug). Vergelijk het aantal instanties van belangrijke klassen: als het aantal Activity is toegenomen, terwijl alle activiteiten zijn gesloten — is er sprake van een lek. Android Studio en Eclipse MAT ondersteunen automatische vergelijking van dumps met markering van verschillen. Volgens Google maakt het vergelijken van dumps het mogelijk om lekken te vinden die bij een eenmalige analyse onzichtbaar zijn door accumulatie van het effect.

Praktische aanbevelingen voor het verminderen van geheugengebruik

Op basis van heap dump-analyse in echte projecten zijn bewezen optimalisatiepraktijken ontwikkeld. Gebruik WeakReference voor caches, callbacks en verwijzingen naar context in langlevende objecten. Meld listeners af in onPause/onDestroy voor Android en deinit voor iOS. Vermijd grote statische collecties — als ze noodzakelijk zijn, gebruik dan LruCache met een groottelimiet. Optimaliseer Bitmaps: laad afbeeldingen met de juiste inSampleSize, gebruik Glide of Picasso met een schijf-cache.

Geheugenprofilering tijdens ontwikkeling

Neem regelmatig vastleggen van heap dumps op in CI. Configureer een taak die geïnstrumenteerde UI-tests uitvoert, belangrijke gebruikersscenario's doorloopt en de heap dump vergelijkt met een baseline. Als de retained size meer dan 5% boven de baseline is gestegen, wordt de build gemarkeerd als regressie. Deze aanpak wordt toegepast bij Airbnb, Uber en andere bedrijven met hoge kwaliteitseisen. Volgens Uber Engineering heeft de implementatie van automatische heap dump-analyse in CI het aantal geheugengerelateerde bugs in een kwartaal met 70% verminderd.

groovy
// Voorbeeld Gradle-taak voor automatische heap dump in CI
task profileMemory(type: Exec) {
    commandLine 'adb', 'shell',
        'am start -n com.example/.MainActivity'
    // Wachten op laden
    doLast {
        exec { commandLine 'adb', 'shell',
            'am broadcast -a com.example.DUMP_HEAP' }
    }
}

Veelgestelde vragen

Wat is het verschil tussen shallow size en retained size?

Shallow size — de grootte van het object zelf (velden + header). Retained size — de grootte van het object plus alle objecten die afval worden bij verwijdering. Retained size is de belangrijkste indicator van de impact van een object op het geheugenverbruik.

Hoe maak ik een heap dump op een fysiek Android-apparaat?

Via Android Studio Profiler selecteert u het apparaat en proces en klikt u op Dump Java Heap. Alternatief — via de opdrachtregel: adb shell am dumpheap PID /sdcard/dump.hprof, gevolgd door adb pull.

Waarom kan een heap dump enorm zijn (500 MB+)?

Een heap dump omvat alle levende objecten. Als de app caches, Bitmaps gebruikt of grote gegevens verwerkt, kan de dump honderden megabytes bereiken. Filter op klasse of gebruik Eclipse MAT om alleen de index te laden.

Kan ik een heap dump analyseren zonder Android Studio?

Ja, gebruik Eclipse MAT (Memory Analyzer Tool) — een gratis tool voor het analyseren van .hprof. Het ondersteunt dominator tree, path to GC roots, dumpvergelijking en automatisch zoeken naar lekken via Leak Suspects Report.

Vermindert een heap dump de prestaties van de app?

De dump zelf — ja, omdat het maken van een dump alle threads onderbreekt (stop-the-world). Zonder dump — nee. Maak een dump onder gecontroleerde omstandigheden (testomgeving, CI), niet in productie.

Samenvatting

  • Heap Dump — een volledige momentopname van de heap van een app met informatie over elk object en de verbanden ertussen.
  • Android Studio Memory Profiler en Xcode Instruments Allocations — de belangrijkste tools voor het vastleggen van dumps.
  • Shallow size — de grootte van het object zelf; retained size — de grootte van het object met de hele subgraph van afhankelijkheden.
  • Dominator tree — de dominatorboom die objecten toont die het meeste geheugen beheren.
  • Path to GC Roots — de keten van sterke verwijzingen die een object verhindert te worden opgeruimd door de garbage collector.
  • Vergelijken van twee heap dumps (voor/na actie) — de meest betrouwbare methode om lekken te detecteren.
  • Automatisering van het vastleggen en analyseren van heap dumps in CI voorkomt geheugenregressies in de ontwikkelfase.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook