Understanding Memory Leaks in ActionScript (Adobe Flex)

来源:互联网 发布:陆良县多年气象数据 编辑:程序博客网 时间:2024/04/30 23:46
 

Thanks go to Danny of TheGoldHold.com for a bunch of this information!

In ActionScript, there is no method to manually completely remove anobject from memory. That task is soley the responsibility of the FlashPlayer's garbage collector (GC). The GC operates autonomously, andbeyond the "Force GC" button in the Flex Builder memory profiler, thereis no method to cause the GC to run. Therefore, memory leaks in Flexcan be hard to understand and debug.

I have created a MemoryLeakTest projectin Flex Builder that show examples that are and are not memory leaks.The project contains three applications, two with memory leaks and onewith out. Each sample application adds and removes a singlesub-component 100 times per second. This forces the garbage collectorto run, and easily shows when a memory leak occurs. The source codecontains 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 limitedby the browser. Therefore, instead of making a large number of smallrequests for memory, flash player makes a small number of requests forlarge chunks of memory. Memory deallocation is also a slow process, soflash player is reluctant to give up memory; though it will do so asnecessary.

Garbage Collector Specifics

Objects are garbage collected only when they have no other objectsthat contain strong references. Flash Player's runtime keeps areference table that is updated each time a reference is made betweentwo objects. The Garbage Collector simply uses that table to determinewhich objects are completely de-referenced.

The Garbage Collector (GC) runs directly before additional memory isrequested. This way flash player can gain the memory resources used bygarbage objects, and can re-evalute the need to allocate additionalmemory; possibly saving time. It is important to note that GC does notrun immediately when an object is completely de-referenced. So, eventhough you've completely de-referenced an object it can and probablywill stay in memory.

Identifying Memory Leaks

Flex Builder 3 Pro includes a "Profiler" tool that can be used toidentify memory leaks. In that tool is a "Force Garbage Collection"button. When your application is being profiled, simply click thatbutton and monitor the "Live Objects" list. If you believe you havecomplete removed and dereferenced an object, its number of "instances"should have be reduced.

Use the "Cumulative Instances" to determine how many instances ofthat object were ever created, and the "Instances" column to determinehow many of those instances still exist. If after creating and removingan 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 amemory leak exists; but only for small applications. The red linerepresents the maximum memory use, and the blue line represents thecurrent memory use. If the blue line and red line never separate, youhave a memory leak.


Bad Memory Usage


Good Memory Usage

Memory Leaks by Reference

Because the garbage collector determines which objects to free bytheir references, it is important for the developer to keep up withwhat references they have created. A very simple example of this iscreating a reference from a parent object to a child object.

In the following example, a childObject is created, and then asecond reference is made to that childObject. Because that secondreference still exists at the end of this code, that childObject willnever 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 memoryleaks in ActionScript. EventListeners push references of the callbackobject into an array on the target object. That reference keeps theGarbage Collector from destroying the call back object. There are a fewexceptions to this rule. These do not block garbage collection:

  1. Weak References
  2. Self References
  3. References to Child Objects

Weak references are created by setting fifth argument of"addEventListner" to "true". By default, eventListeners use strongreferences. Note that using a weak referenced eventlistner, and thenhaving no other reference to an object means that object will begarbage 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. Acommon example is adding an eventListener to a component, and handlingit 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 parentobject is garbage collected, that destroys the references to the childobject. So usually, this means the child object will also be garbagecollected (unless outside references to that child object exist).Therefore, it is safe to add eventListeners to an immediate childobject and not worry about memory leaks. You should note that the childobject 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);