Le garbage collector est le processus responsable de la désallocation mémoire des objets non utilisés. Comme nous allons le voir, une bonne connaissance de son fonctionnement est nécessaire pour qui veut réaliser une application qui ne monopolise pas 100% des ressources système après 10 minutes d’utilisation…
Le garbage collector utilise deux méthodes pour savoir si un objet est actif ou non: le compteur de référence (reference counting) et les marques de balayage (mark sweeping).

  • Compteur de référence.
    Chaque objet possède un compteur dont le rôle est d’indiquer le nombre de références associées. Lorsque le compteur indique 0, c’est le signe que plus aucune référence ne pointe vers l’objet en question et qu’il peut donc être libéré de la mémoire. Ce système est simple à mettre en place et fonctionne bien la plupart du temps, sauf dans les cas de références circulaires (a pointe vers b qui pointes vers a). À partir de la version 8 du Flash Player, ce type de situation n’échappe plus au garbage collector grâce à la technique du mark sweeping.
  • Mark sweeping.
    La machine virtuelle part de la racine de l’application et parcourt de manière récursive tous les objets qui lui sont liés, directement ou indirectement. Elle recense ainsi tous les objets actifs. Une fois l’opération terminée, elle peut donc déduire que les objets non recensés sont inactifs et peuvent être libérés.

L’ennui, c’est qu’il est impossible de savoir exactement quand le garbage collector libérera de la mémoire les objets inactifs. Ce processus réalise en effet un certain nombre de vérifications heuristiques (allocation de la mémoire vive, état de la pile entre autres choses) pour déterminer quand le nettoyage doit avoir lieu. La conséquence directe de ce mode de fonctionnement est que des objets inactifs depuis un certain temps peuvent continuer à utiliser les ressources de votre système, comme le montre cette animation, et vous n’avez aucun moyen pour forcer leur suppression.

De plus, supprimer les références pointant vers un objet donné semble plus facile à dire qu’il n’y parait car, dans la pratique, de très nombreuses références vers les objets de votre application sont créées de manière transparente, lorsque vous mettez en place des écouteurs par exemple. Et de fait, les écouteurs sont la principale cause de fuite mémoire, c’est à dire d’espace mémoire gaspillé par des objets dont la logique voudrait qu’ils ne soient plus référencés (plus d’information sur le le modèle événementiel d’ActionScript ici). Avant de supprimer un objet, il faudra donc s’assurer que ce dernier ne joue pas le rôle d’écouteur.
Il convient d’insister car beaucoup de fausses informations sur le sujet circulent sur internet: lorsque vous déclarez un écouteur, c’est bien le diffuseur qui possède une référence vers l’écouteur et non l’inverse. Autrement dit dans le code suivant:

var monObjetPerso:ClassePerso = new ClassePerso();
var monClip:MovieClip = new MovieClip();
 
monClip.addEventListener( Event.ENTER_FRAME, monObjetPerso.ecouteur );
monObjetPerso = null;  //tentative de libération de la mémoire

Ici, malgré la libération explicite, l’objet monObjetPerso restera en mémoire parce que l’objet monClip l’a référencé dans sa liste des écouteurs de l’évènement ENTER_FRAME. Pour bien faire il aurait fallu auparavant appeler:

monClip.removeEventListener(Event.ENTER_FRAME, monObjetPerso.ecouteur);

Il existe une alternative permettant de passer outre la suppression manuelle des écouteurs: avec la version 3 d’ActionScript est apparu le concept de référence faible (weak reference) permettant d’indiquer à la machine virtuelle que la référence générée lors de l’ajout d’un écouteur ne doit pas être prise en compte par le garbage collector. Le code suivant n’induira donc pas de fuite de mémoire:

var monObjetPerso:ClassePerso = new ClassePerso();
var monClip:MovieClip = new MovieClip();
 
// creation de l'ecouteur. Les paramètres 3 et 4 sont les paramètres par défaut, le dernier paramètre est passé à true pour indiquer une référence faible
monClip.addEventListener( Event.ENTER_FRAME, monObjetPerso.ecouteur, false, 0, true );
monObjetPerso = null;

Conclusion
La détection des fuites de mémoire est une tâche longue et pénible à réaliser. Deux outils permettent toutefois de faciliter cette opération: le profiler disponible dans la version Premium du Flash Builder et le module libre KapInspect.

Mes sources: ici, ici et .