Introduction
In a Flex application, the programmer decides when to allocate memory, simply by using the new operator. However, the developer has absolutely no control over when the memory is freed, because it is done by the “Garbage Collector”.
The Garbage Collector
The GC uses a ‘mark and sweep’ method, which requires at least two passes:
The first pass starts at a set of known “top-level” points (Stage, child objects, static variables and local variables) and traces down through all the referenced objects and marks them as it goes. It’s interesting to note that local variables are included in this pass – more on that in the next sections.
The second pass iterates over the entire list of allocated objects, and decides how many of these (if any) need to be freed up to satisfy the current memory request.
To complicate matters further, the memory allocation process allocates in large chunks and then sub-allocates those chunks for smaller objects. The GC will only delete objects when they are in a chunk where all the objects within it are marked for deletion.
This results in strange behaviours that you can see in the Flex profiler – the total memory will appear to increase and then suddenly drop as a chunk is released. Eventually, the system will reach a point where the system can satisfy every memory request by freeing up other chunks.
Ensuring that an object is free to be collected
For an object to be marked by the first pass of the GC, it must have no references from the top level objects. Prime candidates for stopping an object being collected are as follows:
- Static variables
- Class variables
- Event listeners
This last point requires clarification.
It is the event dispatcher that holds a reference to the listening class (not the other way around)
public class PopupWindow extends TitleWindow { public function PopupWindow() { super();addEventListener( FlexEvent.CREATION_COMPLETE, onCreationComplete); }public function onCreationComplete(event:Event):void {}}
This PopupWindow will be collected without any problem because the addEventListener() call adds a reference to itself.
public class PopupWindow extends TitleWindow { public function PopupWindow() { super();stage.addEventListener(MouseEvent.CLICK, onMouseClick); }public function onMouseClick(event:MouseEvent):void { trace("Stage mouse-click"); } }
This one won’t. The reason is that stage now has a reference to an instance of PopupWindow. As stage will never go away during the life of the application, neither will an instance of PopupWindow.
Further considerations
The Garbage Collector is called as a result of something calling the new operator, not as a background task. In other words, the system wants more memory, so it goes about seeing if it can make any room elsewhere before allocating a completely new block. So if the application is sitting idle, you won’t see the memory change at all in the Profiler.
This is why local variables are included as “top level” objects, because they will still be referencing objects at the point where new is called.
You have no control over when an object is freed. So don’t expect the count of instances to go to 0 when you think that all the references have been removed. You will have to wait until the system decides that it needs to free up those memory block to satisfy another request.
The first pass of collection traces down objects from the top level and marks them. In other words, ”’any”’ objects that don’t have a chain of references from a top level object can be marked for deletion. In the diagram here, the objects in white can be marked for deletion, even though they have a circular link, because there is no link to the root object.
Effects
Effects can be a major contributor to memory leaks because they retain references to the target UI object. In addition, the EffectsManager listens for resize events and can then restart an effect so that it does not end when you expect it to, thus retaining a reference.
Make sure you use the in-built effects if possible, for example creationCompleteEffect and removedEffect as these are fired at the correct time by the framework, and cleared up afterwards as well.
Links
This Powerpoint presentation Garbage Collection by Alex Harui gives some background into how the garbage collector works and what needs to happen to free up objects.
This tutorial here has a lot of info on how garbage collection works, and I nicked some pictures from it…

