Thanks go to Danny of TheGoldHold.com for a bunch of this information!
In ActionScript, there is no method to manually completely remove an object from memory. That task is soley the responsibility of the Flash Player's garbage collector (GC). The GC operates autonomously, and beyond the "Force GC" button in the Flex Builder memory profiler, there is no method to cause the GC to run. Therefore, memory leaks in Flex can be hard to understand and debug.
I have created a MemoryLeakTest project in Flex Builder that show examples that are and are not memory leaks. The project contains three applications, two with memory leaks and one with out. Each sample application adds and removes a single sub-component 100 times per second. This forces the garbage collector to run, and easily shows when a memory leak occurs. The source code contains comments that explain the memory leaks, and how to avoid them, but I'll go over them briefly here as well.
Flash Player Memory Allocation
Memory allocation speed inside the Flash player runtime is limited by the browser. Therefore, instead of making a large number of small requests for memory, flash player makes a small number of requests for large chunks of memory. Memory deallocation is also a slow process, so flash player is reluctant to give up memory; though it will do so as necessary.
Garbage Collector Specifics
Objects are garbage collected only when they have no other objects that contain strong references. Flash Player's runtime keeps a reference table that is updated each time a reference is made between two objects. The Garbage Collector simply uses that table to determine which objects are completely de-referenced.
The Garbage Collector (GC) runs directly before additional memory is requested. This way flash player can gain the memory resources used by garbage objects, and can re-evalute the need to allocate additional memory; possibly saving time. It is important to note that GC does not run immediately when an object is completely de-referenced. So, even though you've completely de-referenced an object it can and probably will stay in memory.
Identifying Memory Leaks
Flex Builder 3 Pro includes a "Profiler" tool that can be used to identify memory leaks. In that tool is a "Force Garbage Collection" button. When your application is being profiled, simply click that button and monitor the "Live Objects" list. If you believe you have complete removed and dereferenced an object, its number of "instances" should have be reduced.
Use the "Cumulative Instances" to determine how many instances of that object were ever created, and the "Instances" column to determine how many of those instances still exist. If after creating and removing an object, then running "Force GC", those numbers are still the same, you probably have a memory leak.
The "Memory Usage" chart is another way to determine whether a memory leak exists; but only for small applications. The red line represents the maximum memory use, and the blue line represents the current memory use. If the blue line and red line never separate, you have a memory leak.
Memory Leaks by Reference
Because the garbage collector determines which objects to free by their references, it is important for the developer to keep up with what references they have created. A very simple example of this is creating a reference from a parent object to a child object.
In the following example, a childObject is created, and then a second reference is made to that childObject. Because that second reference still exists at the end of this code, that childObject will never be freed; unless the parent object is garbage collected.
private var childObject:Object = {test: 'test'};
private var secondReference:Object = childObject;
childObject = null;
Memory Leaks by Event Listeners
Incorrect use of EventListners are the number one cause of memory leaks in ActionScript. EventListeners push references of the callback object into an array on the target object. That reference keeps the Garbage Collector from destroying the call back object. There are a few exceptions to this rule. These do not block garbage collection:
- Weak References
- Self References
- References to Child Objects
Weak references are created by setting fifth argument of "addEventListner" to "true". By default, eventListeners use strong references. Note that using a weak referenced eventlistner, and then having no other reference to an object means that object will be garbage collected, so be careful!
An example of a weak reference event listener.
someObject.addEventListener(MouseClick.CLICK, handlerFunction, false, 0, true);
Self references are simply references by an object to itself. A common example is adding an eventListener to a component, and handling it inside of that component.
An example of a self reference event listener.
this.addEventListener(MouseClick.CLICK, handlerFunction);
Child references are references to a child object. When a parent object is garbage collected, that destroys the references to the child object. So usually, this means the child object will also be garbage collected (unless outside references to that child object exist). Therefore, it is safe to add eventListeners to an immediate child object and not worry about memory leaks. You should note that the child object will not be freed until the parent object is freed!
An example of a childObject event listener:
private var childObject:UIComponent = new UIComponent;
addChild(childObject);
childObject.addEventListener(MouseEvent.CLICK, clickHandler);