AS3: Weak references
Par Stéphane Bebrone le mardi, août 1 2006, 22:20 - Flash - Lien permanent
Si vous suivez un tant soit peu la blogosphère internationale, vous aurez très certainement remarqué (et lu attentivement) que Grant Skinner a commencé la rédaction de plusieurs articles ayant pour toile de fond le sujet plus que jamais critique qu'est la gestion des ressources sous l'AVM 2. Pour les moins anglophones d'entre vous, je vous propose une adaptation libre du thème afin que vous puissiez plus aisément l'assimiler et le mettre en pratique.
Table des matières
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.
actionscriptpackage { 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é!):
actionscriptthis.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!
Commentaires
merci beaucoup pour cet article ;)
maintenant, vivement qu'on puisse avoir d'autres moyens d'utiliser des weak references... parce que je sens qu'il va y en avoir des problèmes de mémoire sous flash
par contre, comme l'a dit skinner, c'est bizarre que l'argument flag weak ne soit pas par défaut sur true
Oui gros problème dans un sens cette notion de controle complet de la mémoire et des références mises en places. En AS2 dans Vegas j'avais implémenter un autoRemove dans ma classe EventDispatcher mais il est clair que la gestion se face directement au niveau du garbage collector et bien c'est pas plus mal :) Pour le reste faudra voir comment va évoluer encore l'AS3.. à mon avis il n'y a pas encore tout ;) Vivement la suite !!
EKA+ :)
à noter que la class flash.utils.Dictionary prend un paramètre équivalent à l'instanciation :
et heureusement ;)
merci a toi de prendre le temps d'ecrire tout ca, ca aide beaucoup de monde et moi le premier, de lire un article dans notre langue :)
article langue ?
Cool, merci pour les news
Merci pour ce tuto
Merci beaucoup