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:
-
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).
-
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.
-
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).