Table des matières

  1. Définition
  2. Avantages
  3. Cas pratique
  4. Ressources

Définition

En une phrase, les weak refererences ou références faibles sont des références qui ne seront pas prises en compte par l'algorithme du Garbage Collector.

Souvenons-nous que le but d'un GC est de veiller à la bonne tenue de la mémoire vive en déchargeant automatiquement (sans intervention de notre part) les objets devenus obsolètes. Une instance étant marquée comme à supprimer dès qu'elle n'appartient plus à aucun graphe de chemin d'objets (tracés depuis les références racines).

Avantages

Leur avantage est évident puisqu'elles permettent au développeur de donner au GC le droit d'effacer un objet bien qu'il possède encore des références. Ainsi, il pourra pointer vers un objet pouvant ou devant être détruits sans se soucier de supprimer cette référence par la suite et réduisant de cette façon les risques de memory leak (fuite de mémoire) qui se révèlent souvent atroces à débugger.

Attention toutefois, en pointant un objet avec ce type de référence vous admettez qu'il n'est pas critique et qu'il peut donc être supprimé à tout instant par le passage du GC (chose que vous ne contrôlez pas). C'est pourquoi il faut mieux toujours vérifier avant chacune de ces utilisations que ce pointeur est toujours valide.

Cas pratique

L'utilisation des weak references en ActionScript 3 est limitée puisqu'elles n'existent pas sous la forme d'un type propre comme on peut en trouver dans la plateforme .NET ou encore Java mais plutôt en tant que paramètre (type boolean) de certaines méthodes ou constructeur. Toutefois dans les commentaires de son article, GSkinner a annoncé la publication prochaine d'un tips qui permettrait d'étendre le spectre de leur utilisation.

Concrètement, la méthode addEventListener qui a comme 5e paramètre ce flag weak reference est un très bon exemple de leur nécessité. En effet, combien de développeurs n'oublient-ils pas de faire un removeEventListener après traitement? Ceci ayant comme résultat l'impossibilité pour l'objet écouteur de se faire collecter, même étant mis à null.

Prenons cette simple class, où j'initialise un objet ListenerDelegate local au scope de mon constructeur. En toute bonne logique, sorti de cette fonction mon écouteur devrait ne plus exister et donc mon trace s'arrêter.

actionscript
package { import flash.display.Sprite; import flash.events.Event;   public class TestWeakReferences extends Sprite { public function TestWeakReferences() { var d:ListenerDelegate = new ListenerDelegate(); this.addEventListener(Event.ENTER_FRAME, d.displayCounter, false, 0, false); }   } }

Or on remarque, que le trace continue de fonctionner (et donc l'objet d'exister) comme si cette référence était déclarée comme variable d'instance. Tout simplement, le GC ne peut collecter notre delegate étant donné que celui-ci conserve une référence (ajoutée via addEventListener) à l'émetteur.

Si maintenant, on lui demande explicitement de ne pas tenir compte de cette référence en passant le 5e paramètre à true (comme recommandé!):

actionscript
this.addEventListener(Event.ENTER_FRAME, d.displayCounter, false, 0, true);

Force est de constater que tout se passe comme prévu, notre code est bel et bien protégé des scripts fantômes et des fuites de mémoires.

Ressources

[UPDATE] Grant Skinner vient de publier son tips pour élargir le contexte d'utilisation des Weak References dont je faisais mention ci plus haut. Il donne en plus une manière de procéder pour forcer le GC à collecter les objets (attention à n'utiliser qu'en cas de tests!) et termine par une explication de la nouvelle propriété de la classe System: System.totalMemory. A lire absolument donc!