Sobes.tech
Middle+

Comment détecter une fuite de mémoire lors de l'analyse d'un dump ?

sobes.tech IA

Réponse de l'IA

Pour détecter les fuites de mémoire dans un dump (fichier HPROF), on utilise des outils qui analysent le graphe d'objets dans le tas. Étapes principales:

  1. Obtenir le dump mémoire :

    • Via le Memory Profiler d'Android Studio.
    • Avec la commande adb shell dumpheap <nom_du_package> /data/local/tmp/dump.hprof.
    • Avec l'appel système Debug.dumpHprofData(filePath).
  2. Analyser le dump :

    • Ouvrir le dump dans Android Studio : dans Memory Profiler ou via le menu "Fichier" -> "Ouvrir".
    • Analyse des objets : trier les objets par taille (Shallow Size, Retained Size) et nombre d'instances.
    • Rechercher des objets suspects : cherchez des classes qui devraient être détruites (par exemple, Activity, Fragment, Contexts) mais ont beaucoup d'instances ou une taille retenue importante.
    • Étudier le chemin vers l'objet (Chaîne de références) : sélectionnez un objet suspect et tracez son chemin vers les objets racines (GC roots). Cela montrera qui maintient la référence, empêchant la collecte de déchets.
    • Rechercher des références statiques : les champs statiques sont souvent une source de fuite s'ils stockent des références de longue durée à des contextes ou vues.
    • Utiliser LeakCanary : la bibliothèque automatise la détection, le dump et l'analyse des fuites en temps réel, fournissant une description détaillée du chemin de la fuite.
  3. Interprétation des résultats :

    • Un chemin long vers GC root contenant des références à des objets qui devraient être détruits indique un problème.
    • Les références depuis des champs statiques, AsyncTask, Handlers avec des délais, des listeners/callbacks non désenregistrés correctement, ou des singletons dans des activités ou vues, sont souvent la cause des fuites.

Exemple d'analyse du chemin vers GC root dans Android Studio Memory Profiler :

// Exemple de chemin vers GC root indiquant une fuite
// android.app.Activity instance avec mDestroyed=true
//   référence à android.widget.LinearLayout
//     référence à android.view.View $ListenerInfo
//       référence à com.example.MyActivity$1 (classe anonyme implémentant View.OnClickListener)
//         référence à com.example.MyActivity (référence fuyant)

Dans cet exemple, une classe anonyme (écouteur de clic sur le bouton) maintient une référence implicite à MyActivity, bien que l'activité devrait déjà être détruite (mDestroyed=true). Cet écouteur semble être enregistré ou retenu par un autre objet de longue durée (par exemple, un champ statique ou un singleton).