Heap Dump : qu'est-ce que c'est, analyse du heap et élimination des fuites mémoire

Auteur : IT Sectr Publié le : 2026-05-07 Temps de lecture : 10 min

Heap Dump (dump du heap) est un instantané de la mémoire dynamique d'une application contenant des informations complètes sur tous les objets vivants : leurs classes, tailles, références mutuelles et accessibilité depuis les racines GC. Heap Dump est l'outil principal pour analyser les fuites mémoire et optimiser la consommation des ressources. Selon Android Developers, l'analyse des heap dumps permet de détecter jusqu'à 95 % des fuites mémoire, y compris les références cycliques, les listeners oubliés et les références statiques non libérées.

Points Clés

  • Heap Dump est un instantané de toute la mémoire dynamique de l'application avec des informations sur chaque objet et les références entre eux.
  • Android Studio Memory Profiler permet de capturer des heap dumps en temps réel pour les applications Java et Kotlin.
  • Xcode Instruments fournit l'outil Allocations pour créer et analyser des heap dumps sur iOS/macOS.
  • Shallow et retained size sont les métriques clés : shallow est la taille de l'objet lui-même, retained est la taille de l'objet plus tous les objets qu'il retient.
  • L'analyse d'un heap dump inclut la recherche dans le dominator tree, les plus gros retained objects et les chemins les plus courts vers les racines GC.

Qu'est-ce qu'un heap dump et à quoi sert-il

Heap dump est un vidage complet du heap de la machine virtuelle — la zone mémoire où résident tous les objets créés dynamiquement. En Java et Kotlin, c'est le heap Dalvik/ART sur Android, en Swift et Objective-C, c'est le heap géré par ARC sur iOS. Un heap dump capture chaque objet, sa classe, sa taille, ses champs, ses références vers d'autres objets et les indicateurs d'accessibilité depuis les racines GC (variables de pile, champs statiques, références JNI).

L'objectif principal d'un heap dump est la détection des fuites mémoire. Une fuite se produit lorsqu'une application continue de maintenir des références vers des objets qui ne sont plus nécessaires, empêchant leur collecte par le garbage collector. Causes typiques : des listeners d'événements non désenregistrés à la destruction d'une activity ; des singletons avec des références au contexte ; des closures qui capturent self ; des collections statiques où des données sont ajoutées sans suppression. Un heap dump fournit une image précise : quels objets sont « vivants », lesquels sont superflus et qui exactement les référence.

Selon Google I/O, plus de 60 % des rapports de crash d'applications Android sont liés à OutOfMemoryError, et dans 80 % des cas, la cause première est une fuite mémoire détectable via heap dump. Pour les applications iOS, la situation est similaire : les fuites dues aux retain cycles sont l'une des causes les plus fréquentes de crashes, identifiées via l'instrument Allocations dans Xcode.

Quand un heap dump est nécessaire

Un heap dump doit être réalisé lorsque les symptômes suivants apparaissent : l'application consomme de la mémoire linéairement lors d'actions répétitives (navigation aller-retour entre écrans) ; après la fermeture d'un écran, la mémoire ne revient pas au niveau de base ; des OutOfMemoryError ou des avertissements mémoire sur iOS surviennent ; l'application se termine pour dépassement de limite mémoire (EXC_RESOURCE_RESOURCE sur iOS). La collecte régulière de heap dumps fait partie du protocole de culture d'ingénierie dans les grands projets mobiles comme Instagram et Spotify.

Heap dump dans Android Studio : obtention et analyse

Android Studio fournit Memory Profiler — un outil intégré pour capturer des heap dumps en temps réel. Accessible via View → Tool Windows → Profiler. Après le lancement de l'application, sélectionnez la session, allez dans l'onglet Memory et cliquez sur Dump Java Heap. Android Studio suspend l'application, effectue un dump du heap ART et charge le résultat pour analyse. Le fichier de dump est au format .hprof — le standard HPROF compatible avec la plupart des analyseurs mémoire.

Après le chargement du dump, Android Studio affiche un tableau d'objets avec des colonnes : Allocations (nombre d'instances), Native Size (mémoire hors heap ART), Shallow Size (mémoire de l'objet lui-même), Retained Size (mémoire de l'objet incluant tout son sous-graphe). Le filtrage par nom de classe, le tri par retained size et la recherche par paquets permettent de trouver rapidement les zones problématiques.

kotlin
// Fuite typique — un listener non désenregistré dans 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) manquant
        // → L'Activity ne sera pas collectée par le GC, le heap dump montrera la fuite
    }
}

Analyse du dominator tree dans Android Studio

L'onglet Dominator Tree montre les objets qui retiennent le plus de mémoire. Si un objet est supprimé du dominator tree, toute la mémoire qu'il retient devient disponible pour la collecte. C'est un outil clé : au lieu d'examiner des milliers d'objets, vous vous concentrez sur 10 à 20 qui contrôlent 80 à 90 % de la mémoire. Selon Google, l'analyse du dominator tree est le moyen le plus efficace de trouver un point de fuite, réduisant le temps d'analyse de heures à minutes.

Heap dump dans Xcode Instruments : Allocations et Leaks

Xcode Instruments fournit deux outils pour travailler avec les heap dumps : Allocations — capture de dumps de heap avec graphique de consommation en temps réel ; Leaks — recherche automatique de fuites via l'analyse des retain cycles. Allocations affiche tous les objets dans le heap, leur taille, le nombre de créations (allocations) et de libérations (deallocations). La différence entre le nombre de créations et de libérations pour une classe spécifique indique une fuite potentielle.

La capture d'un heap dump dans Allocations se fait avec le bouton Snapshot Memory — l'outil suspend l'application et prend un dump complet. Ensuite, les vues standard sont disponibles : liste d'objets par classe, arbre d'appels (call tree) pour chaque objet et un générateur de rapports. Contrairement à Android Studio, Xcode n'utilise pas .hprof mais stocke les données dans son propre format .trace compatible avec Instruments.

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

    func startRequest() {
        // ❌ La closure capture self — retain cycle
        onComplete = { data in
            self.process(data)
        }
    }
    func process(_ data: Data) {}
}

L'instrument Leaks détecte automatiquement les retain cycles et les fuites via l'analyse du graphe de références. Il marque les objets qui fuient avec une icône violette et montre le chemin vers la racine (GC root). Pour éliminer un retain cycle, il suffit d'ajouter [weak self] ou [unowned self] dans la capture de la closure. L'exécution régulière de l'instrument Leaks est une étape obligatoire du pipeline CI dans les équipes utilisant Swift pour le développement iOS.

swift
// Correction — référence faible à self
onComplete = { [weak self] data in
    guard let self else { return }
    self.process(data)
}

Shallow size, retained size et dominator tree

Pour une analyse correcte d'un heap dump, il est nécessaire de comprendre trois métriques clés. Shallow size est le volume de mémoire occupé directement par l'objet : ses champs, son en-tête (header) et son alignement. Pour un objet Java/Kotlin typique, la shallow size est de 16 à 40 octets. Retained size est la shallow size de l'objet plus la somme des shallow sizes de tous les objets qui ne sont accessibles que via cet objet (c'est-à-dire deviendraient des déchets s'il était supprimé). C'est la retained size qui montre l'impact réel de l'objet sur la consommation mémoire.

MétriqueDescriptionExemple
Shallow sizeTaille de l'objet lui-même en octetsBitmap (100 × 100) = 40 016 o
Retained sizeShallow size + tout ce qu'il retientActivity avec View Tree = 2–5 Mo
Deep sizeRetained size + objets imbriqués d'autres graphesScrollView avec adaptateur = 10–50 Mo

Dominator tree est une structure où chaque objet référence son « dominateur » — l'objet qui contrôle son accessibilité. Si le dominateur est supprimé, tous les objets de son sous-arbre deviennent des déchets. L'analyse du dominator tree est le moyen le plus rapide de trouver quel objet retient le plus de mémoire. Selon Eclipse MAT (Memory Analyzer Tool), 90 % des fuites sont détectées en examinant le top-20 du dominator tree en 5 minutes.

Analyse des fuites mémoire via heap dump

Le processus d'analyse d'une fuite via heap dump comprend plusieurs étapes. Étape 1 : effectuez l'action qui devrait libérer la mémoire (fermez l'écran, terminez l'opération). Étape 2 : appelez le GC et faites un heap dump. Étape 3 : trouvez les objets qui auraient dû être détruits. Étape 4 : pour l'objet suspect, exécutez Path to GC Roots — la chaîne de références qui maintient l'objet en vie. La dernière référence dans la chaîne est la cause de la fuite.

Path to GC Roots

La fonction Path to GC Roots est disponible dans Android Studio Profiler, Eclipse MAT et Xcode Instruments. Elle montre la chaîne la plus courte de références d'une racine GC à l'objet problématique. En excluant les références faibles (weak) et douces (soft), vous obtenez seulement les fortes (strong) — celles qui empêchent réellement la collecte. Selon Square Engineering, 70 % des fuites dans les applications Android sont causées par seulement deux motifs : des références statiques vers Activity ou Context et des listeners enregistrés mais non désenregistrés.

kotlin
// Exemple de fuite via une référence statique
object AppCache {
    private val cache = mutableMapOf<String, Any>()

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

// Correction : référence faible
object AppCacheFixed {
    private val cache = mutableMapOf<String, WeakReference<Any>>()
}

Comparaison de deux heap dumps

La technique du mode de comparaison est l'une des méthodes les plus efficaces pour trouver des fuites. Faites un heap dump avant et après une action répétitive. Comparez le nombre d'instances des classes clés : si le nombre d'Activity a augmenté bien que toutes les activités aient été fermées — c'est une fuite. Android Studio et Eclipse MAT prennent en charge la comparaison automatique de dumps avec mise en évidence des différences. Selon Google, la comparaison de dumps permet de trouver des fuites invisibles lors d'une analyse unique grâce à l'effet d'accumulation.

Recommandations pratiques pour réduire la consommation mémoire

Basées sur l'analyse de heap dumps dans des projets réels, des pratiques éprouvées d'optimisation mémoire ont été développées. Utilisez WeakReference pour les caches, les callbacks et les références au contexte dans les objets à longue durée de vie. Désenregistrez les listeners dans onPause/onDestroy pour Android et deinit pour iOS. Évitez les grandes collections statiques — si nécessaires, utilisez LruCache avec une limite de taille. Optimisez les Bitmaps : chargez les images avec le bon inSampleSize, utilisez Glide ou Picasso avec un cache disque.

Profilage mémoire pendant le développement

Intégrez la capture régulière de heap dumps dans votre pipeline CI. Configurez une tâche qui exécute des tests UI instrumentés, effectue les scénarios utilisateur clés et compare le heap dump avec une ligne de base. Si la retained size augmente de plus de 5 % par rapport à la ligne de base, la build est marquée comme régression. Cette approche est pratiquée chez Airbnb, Uber et d'autres entreprises ayant des exigences de qualité élevées. Selon Uber Engineering, l'implémentation de l'analyse automatique de heap dumps dans CI a réduit les bogues liés à la mémoire de 70 % en un trimestre.

groovy
// Exemple de tâche Gradle pour heap dump automatique dans CI
task profileMemory(type: Exec) {
    commandLine 'adb', 'shell',
        'am start -n com.example/.MainActivity'
    // Attente du chargement
    doLast {
        exec { commandLine 'adb', 'shell',
            'am broadcast -a com.example.DUMP_HEAP' }
    }
}

Questions Fréquentes

Quelle est la différence entre shallow size et retained size ?

Shallow size est la taille de l'objet lui-même (champs + en-tête). Retained size est la taille de l'objet plus tous les objets qui deviendraient des déchets s'il était supprimé. La retained size est le principal indicateur de l'impact d'un objet sur la consommation mémoire.

Comment faire un heap dump sur un appareil Android physique ?

Via le Android Studio Profiler, sélectionnez l'appareil et le processus, cliquez sur Dump Java Heap. Alternativement, via la ligne de commande : adb shell am dumpheap PID /sdcard/dump.hprof, puis adb pull.

Pourquoi un heap dump peut-il être énorme (500 Mo+) ?

Un heap dump inclut tous les objets vivants. Si l'application utilise des caches, des Bitmaps ou traite de grandes données, le dump peut atteindre des centaines de mégaoctets. Filtrez par classes ou utilisez Eclipse MAT pour charger seulement l'index.

Peut-on analyser un heap dump sans Android Studio ?

Oui, utilisez Eclipse MAT (Memory Analyzer Tool) — un outil gratuit pour analyser les fichiers .hprof. Il prend en charge le dominator tree, le path to GC roots, la comparaison de dumps et la détection automatique de fuites via Leak Suspects Report.

Un heap dump réduit-il les performances de l'application ?

Le dump lui-même — oui, car la collecte du dump suspend tous les threads (stop-the-world). Sans dump — non. Effectuez les dumps dans des environnements contrôlés (banc de test, CI), pas en production.

Résumé

  • Heap Dump est un instantané complet du heap de l'application avec des informations sur chaque objet et les relations entre eux.
  • Android Studio Memory Profiler et Xcode Instruments Allocations sont les principaux outils de capture de dumps.
  • Shallow size est la taille de l'objet lui-même ; retained size est la taille de l'objet avec tout son sous-graphe de dépendances.
  • Dominator tree montre les objets qui contrôlent la plus grande quantité de mémoire.
  • Path to GC Roots est la chaîne de références fortes qui empêche un objet d'être collecté.
  • La comparaison de deux heap dumps (avant/après une action) est la méthode la plus fiable pour détecter les fuites.
  • L'automatisation de la capture et de l'analyse des heap dumps dans CI prévient les régressions mémoire pendant le développement.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi