All Java developers that start developing software in Flex know what garbage collector is and how it works; the Flash developers, who can be not so well-informed about it, should begin to understand what it is, because the new functionalities introduced into Actionscript 3 can lead to memory leaks.
The garbage collector of actionscript 3 works in 2 different ways to know which object should be deleted from memory: the reference counting method and the mark&sweep.
In the first case every object maintains the number of references to it during the application's execution; when an object is created its reference count starts from 1, every time this object is referenced by others its reference count grows, on the contrary the reference count decreasees when another object with a reference to it is deleted.
When the number of references goes down to 0, then the garbage collector can remove the object from memory.
In the mark&sweep method the flash player starts from the application root object and visits al its referenced object, gradually reaching all the leaves of the reference tree; the flash player marks all the objects met. This way all the objects connected directly or indirectly to the root object will be reached and marked.
At the end of the visit all the objects not marked could be deleted from memory.
The first methid is faster and easier but there are problems like round references, that is those objects that have references between themselves.
The second method, introduced with flash player 8, is a lot more effective, but the visit in depth of the reference tree is really expensive speaking about CPU, so it can be used only sometimes.
It has to be clear to developers that the garbage collector doesn't delete an object from memory immediately. An object remains active for some time and it will keep going listening to and launching events until it will be definitely cancelled.
The biggest risk to create memory leaks comes from event listeners; in actionscritp 3.0 has been added the chance to create listeners with weak reference, that is they will not be considered in reference counting.
//the last parameter is the weakReference flag
object.addEventListener("eventName", listenerFunction, false, 0, true);
This way we don't take the risk that an object will never deleted from memory due to listener fault, anyway there is the possibility to remove the event listener, so we can avoid the risk in any case:
object.removeEventListener("eventName", listenerFunction);
Whe we use a ChangeWatcher on a Bindable propery of an object
var watcher:ChangeWatcher = ChangeWatcher.watch(object, "property", listenerFunction);
we should always remeber to call the unwatch method when the watcher is not necessary anymore
watcher.unwatch();
otherwise it will not be possible anymore to delete the object from memory.
With Java it is possible to call clearly the garbage collector using this two simple istructions:
Runtime r = Runtime.getRuntime();
r.gc();
in flash there in no way to explicitly invoke the garbage collector, but on the web there is a hack that can be found with a simple search:
private function gcHack():void
{
// unsupported hack that seems to force a full GC
try
{
var lc1:LocalConnection = new LocalConnection();
var lc2:LocalConnection = new LocalConnection();
lc1.connect('name');
lc2.connect('name');
}
catch (e:Error)
{
}
}
it seems to work without problems, so we hope to find an official and documented function that does this as soon as possible.
Comments (4)
Uh, I think you mean Flash Player 9... Flash Player 8 could only play ActionScript 1 & 2, and does not even have a garbage collector in the same sense as the VM2.
Posted by Joeflash | April 27, 2008 5:52 PM
Posted on April 27, 2008 17:52
Yes, you are right, but the new garbage collector was introduced in flash player 8, probably the title was a bit confusing ;)
thanks
Posted by Emanuele Tatti | April 28, 2008 5:16 PM
Posted on April 28, 2008 17:16
I posted an interactive simulator for the GC's Mark & Sweep and Reference Count functionality that you can play with here:
http://www.gskinner.com/blog/archives/2006/09/garbage_collect.html
Regards.
Posted by Grant Skinner | April 29, 2008 10:39 PM
Posted on April 29, 2008 22:39
Great article!
However you can explicitly call the GC with flash.system.System.gc();
Only problem with this is that you have to call it twice, once for marks, and once for sweep.
You have to push any existing enterframe handler off the call stack by creating a new one. Adobe took care of the first problem, but to handle the second one we had to change our GC call a bit.
private var gcCount:int;
private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
}
}
more information check this link: http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/
Good luck!
Cheers,
Sidney
Posted by Sidney de Koning | May 4, 2008 3:10 PM
Posted on May 4, 2008 15:10