Ted Patrick - Demos & MAX @ Adobe Systems


Note: This is the personal blog of Ted Patrick. The opinions and statements voiced here are my own.



useWeakReferences:Boolean = false

DIGG IT!     21 Comments Published Monday, September 15, 2008 at 8:42 PM .

This is the last argument in the addEventListener method and it just might be one of the most important. Whenever you subscribe to events you have the option to set useWeakReferences to false (the default) or to true (unfortunately not the default). What seems incredible to me is the fact that this is the last argument and that it defaults to false.

When useWeakReferences is false the following happens:

THE CLASS INSTANCE OF THE SUBSCRIBED METHOD WILL NOT GARBAGE COLLECT.
Even if the instance is destroyed by lightening and crushed by your car, it will remain alive stuck within the addEventListener inner workings til you unsubscribe to the listener. Worse is that you most likely lost the instance that you subscribed and that is required to use removeEventListener successfully. The instance will remain in memory and the method will keep getting called, uggghhhhhhh.

A better way...

When useWeakReferences is true the following happens:

THE CLASS INSTANCE OF THE SUBSCRIBED METHOD WILL GARBAGE COLLECT, AHHHHHHH.
Even if the instance is destroyed by lightening and crushed by your car, it will die and the method subscribed will never be called again.

Garbage collection is a very tricky business. The Flash Player VM is constantly looking for objects without a strong reference to them to collect. The real dilemma is that strong references are very easy to create.

All it takes is one:

var a = foo;

or

var b = foo.method; // yes closures come with an instance reference... :(

or

this.addEventListener( MouseEvent.CLICK , foo.method );

and foo will never garbage collect until 'a' and 'b' are removed as references and removeEventListener is called. With complex apps there can be a ton of events and you need to be super careful with references. References are the devil in the details.

I am knee deep in event code for BX and I am being extra careful to make sure that events are easier to work with. Be careful with references, they can make a real mess if you are not careful.

cheers,

Ted :)

21 Responses to “useWeakReferences:Boolean = false”

  1. # Anonymous Erik

    In 'real' situations you add listeners to children. When you add a listener to a child this problem does not exist. If you add listeners to itself, the problem does not exist.

    The cases where you add listeners to a parent are very rare. The only 'real' case where you need to use weak references is when you add a listener to the stage.

    So a rule of thumb is: when adding a listener to the stage, make sure you set 'weakReferences' to true.


    Greetz Erik  

  2. # Anonymous Erwin Verdonk

    Thanks for blogging about this issue Ted. So many developers who are new to the whole GC thing create memory leaks all over the place without knowing. Eventually when they find out it is one big (almost impossible) task to skim the application and fix the thing.

    The biggest probleem with events is indeed that the "useWeakReference" is default "false". Now when you know that you can workaround it by setting it to "true" in the arguments of addEventListener() or by using removeEventListener() when you dont need it anymore.

    However when you use binding in Flex MXML you are in hell, since you can't workaround it like that. You can't set the "useWeakReference" parameter to "true" and you can't use removeEventListener() because it uses another (wrapper/proxy) handler function behind the scene which you have no reference to.

    My conclusion - but I might be wrong - is that with Flex MXML you create memory leaks instantly when using events. For example use the 'enterFrame' event on a MXML component. Remove the component from the stage and null its references. You'll notice that the 'enterFrame' event keeps firing and the MXML does not get collected.

    Thats why I prefer to never use events directly on MXML until this is fixed. I always put the handlers on events with ActionScript after the 'creationComplete' event, and that is the only event I use with MXML.

    Once again, thanks for bringing this to anyones attention.  

  3. # Blogger richardolsson

    I find best practice is to KNOW what event listeners you have registered, and remove them before unreferencing your object.

    I always write a dispose() function in parallell with all other code in a class, so that as soon as I add an event listener somewhere, I put a line removing it in the dispose() method.

    Of course, strong references are a must if you want to listen for events on objects that are not class scope variables, such as when creating a Loader reference in loadSomeData() and invoking onLoadComplete() on the complete event.

    Otherwise, the Loader would be marked and some times sweeped before the load finishes, aborting the load. In these cases, the first thing I do in the onLoadComplete(ev:Event) handler is ev.currentTarget.removeEventListener(Event.COMPLETE, onLoadComplete).  

  4. # Blogger Mathis

    But in my opionion you should't count on weak references (or the allmighty power of garbage-collection), the clean solution for me is still to remove all event listeners which aren't needed anymore and which your own code did attach. The way of automagically removed listeners led in my experience to code which was less stable than before. Easy: i attach them by myself, i remove them by myself(e.g. in a dispose-function).  

  5. # Blogger Chris Brind

    We spotted this and it was causing the client some problems as we create a fair few objects because of some complicated layouts we've got (we're going to have to re-factor it, I think).

    Anyway, we had a couple of objects which various other objects listen for events from. The problem is, if you explicitly set useWeakReference to true, it means you have to supply a value for the other defaulted arguments which are usually OK. This seemed a bit wrong to me, as surely you should only have to be explicit if you want to have a value other than the default? And in this case we wanted to change the actual default to something else, i.e. true.

    Anyway, the solution was to override the addEventListener method and give it a new signature, then delegate to the super class:


    override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = true):void {
    super.addEventListener(type, listener, useCapture, priority, useWeakReference);
    }


    But obviously, this only works on classes you create which extend EventDispatcher somewhere in the inheritence hierarchy.

    Cheers,
    Chris  

  6. # Blogger Ria Flex

    This is exactly what I tried to warn for when commenting on your Brix my hobby as3 framework post. In case you start using weakReference=true you should make sure not to use an anonymous function to handle the event (because these functions in combination with a weakReference do not always get called).  

  7. # Anonymous Dirk Eismann

    Actually, you don't have to use weak references all over the place - it really depends on where you listen to (i.e. a child or the parent)

    Alex Harui has some nice slides on his blog that make things clearer:

    http://blogs.adobe.com/aharui/2007/03/garbage_collection_and_memory.html

    there you'll find a PPT file which deals with event listeners and GC (see slides 24-27)

    As a sidenote: in Flex, when you use inline MXML statements to create event listeners you have absolutely no control and cannot manually remove event listeners - this is a far more severe problem IMHO.  

  8. # Anonymous Anonymous

    I knew about the issue with weak references in events, but I want to make sure I understand another part of your post: foo won't be garbage collected until I set vars a and b to null?  

  9. # Blogger Ted Patrick

    RIAFlex, True :) In BX I abstract away addEventListener so it doesn't matter. Moving events to names narrows things to one type of reference counting. The strangeness with addEventListner is that most do not realize that these are references and in most cases blind.

    I am not so sure that issues are limited to displayobjects. There are simple techniques for loading data (Images, ByteArray, AMF, XML) where the loaded data can get affected.

    Ted :)  

  10. # Blogger richardolsson

    By the way, there is another reason to remove event listeners by hand. If you rely on the garbage collector to remove them for you, they might execute while "in limbo"; after you removed all references, but before the garbage collector performed a sweep.

    Imagine having a timer, setting an event listener, starting the timer and then removing the reference to both the timer and the listener function. Both still exist in memory and the function will get called, unless you first provoke a garbage collection, which will only happen when memory starts to exhaust.

    Am I not correct in this assumption?

    Anyway, I favour keeping track of your listeners instead of relying on the VM to do it for you! ;)  

  11. # Blogger Ted Patrick

    Method closures are another hidden gotcha. When you obtain a reference to a method of an instance, you actually get a hidden reference to the instance. If you hold onto this, the object will not garbage collect. It is a hidden strong reference.

    Method closures were added to keep methods executing within the scope of the instance they are bound to. If you create a reference to a method of an instance it will always execute in the instance scope.

    The flip side is that this is another type of reference that is hidden from view.

    Ted :)  

  12. # Blogger Nate Chatellier

    Seriously, why does useWeakReference default to false?? Early in the release of ActionScript 3.0, I actually added this to my company's standard programming policies that useWeakReference should always be set to true (unless you use an inline function which we usually frown against anyway). Seems like a totally poor decision to default it to false. Especially because there are many Flash programmers out there that aren't really programmers and would create memory leaks without even knowing or caring. It's little things like this that I believe Adobe could address to help people not complain so much about Flash being a resource hog...  

  13. # Blogger Ted Patrick

    Nate,
    AS3 was really designed with the FX use case in mind given the release dependency 2 years ago. Hindsight is 20/20 but the API does provide support for weak and strong references. Strong references are also very handy as well.

    Nothing like a good sharp knive! It is super handy but it can cut you if you are not careful.

    Ted :)  

  14. # Anonymous Erwin Verdonk

    To extend on my prevously post, the strong references with events by default has far more impact on Flex MXML than just event handling. The whole binding functionality within Flex is built on the event driven architecture of ActionScript 3. When you create a binding within Flex MXML you create a strong reference to another scope (ChangeWatcher) that can never be removed and so garbage collected can not do its work there.

    [b]Binding >> ChangeWatcher >> EventDispatcher(useWeakReference=false) == Strong Reference[/b]

    As Dirk Eismann pointed out as well, the way Flex MXML handles events is a severe problem, that should be addressed immediately, if it hasnt already.

    For the time being it is better not to use too much inline MXML event handling and for binding it is advisable to either use the ChangeWatcher directly or to create your own binding class with more control.

    Ted, can you tell us something about this issue? Is Adobe working on it?  

  15. # Blogger Ted Patrick

    I talked to the player team yesterday about the issue. It seems that there is a bug in Flash Player 9 around this issue. It seems "weak" references were not being garbarge collected and that loaded content (Loader) was not unloading resources.

    These issues are fixed in Flash Player 10. Wooot.

    Also the new bi-directional binding in Flex 4 should address the issue as well.

    Ted :)  

  16. # Blogger florian.salihovic

    Just stumbled across this entry searching for a Flex Postcast...

    I think the developers should care more about the structures in general. I recommend thinking in state machines for example, when it comes to eventlisteners and DisplayObject instances. The only eventListener which is registered with a weak reference to the instance is Event.ADDED. The rest is referenced with strong references and added or removed when needed to not.

    And developers should also read the API... many don't even know about the additional parameters or don't care about what happens in the background.

    Thanx though for the article... it was a nice read.

    Best regards!  

  17. # Blogger Beau Scott

    A handy thing with regard to anonymous functions used as event handlers: arguments.callee

    Example:

    foo.addEventListner(Event.TYPE, function(event:Event):void {
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    ...
    });  

  18. # Blogger jrevel

    Be careful with weakReferences on listeners : in some situations, your listener may be garbaged BEFORE the object itself, so that there will be no listener called at all.
    This situation may arise if, for example, you create "floating out" object listeners, with no reference on them at all, excepted those on the listeners.
    So for me, using weakReference systematically is not a good practice either
    Kohinoor  

  19. # Anonymous erixtekila

    Hi Ted,
    Maybe you could talk to the player's team and ask them if useWeakReference=true couldn't produce longer process for the Garbage Collector ?

    At first, it seems that this parameter should have been set to true by default.
    But thinking twice about the inner working, the ways to track weak references that have to be garbaged automatically should be quiet intensive for the GC.

    Could you please enlight us about that possibility ?  

  20. # Anonymous erixtekila

    hm, no time maybe to ask to the player's team ?!
    Email me viacontact{at}v-i-a.net if possible once you'll get time.
    Thanks by advance.  

  21. # Anonymous Anonymous

    If we add two different event listener on one object with useWeakReferences = true, will the object be GC?  

Post a Comment

Where to find me:

Ted on Twitter - @AdobeTed
Ted on Adobe Groups
Ted on LinkedIn
Ted on Facebook
Ted at Adobe


Latest

Lists

Links

Jobs

Flex Jobs
city, state, zip

Archives