Every time you use the "new" keyword to create an object, you're staking your claim on a piece of memory [1]. So let's say you're making a uint by writing var exampleUint:uint = new uint();
. ActionScript says to the computer "hey... I need like... four bytes of memory.", to which the computer replies "ok cool, use the four bytes starting at [some memory address, like 0x7B3208C1]"[2]. So when you say var someString:String = "blah";
you claim a space in memory, fill it with some information (in this case, it's "blah"
), create a label (in this case, it's someString
), and bind the label to that space in memory.
Now the label doesn't actually associate to the data itself, it associates to the spot in memory containing the data. That should seem confusing, because it is, but it makes a whole shit-ton of sense for certain reasons. All objects in ActionScript are reference types, which means that the object contains the memory address of some piece of data, not the data itself. This is in contrast to objects that are value types, where a label associates to the data itself. Don't fret about the details on value types because it's not in ActionScript so for your purposes I'm including it strictly for contrast. OK, confused? You probably should be, because this whole paragraph is needlessly specific and probably even unnecessary, but try to keep it in the back of your head because it may have something to do with your problem.
Now, when that label is gone (e.g., it goes out of scope, so now someString
is meaningless), only the label someString
is removed. So for this example, if you say someString = null;
, the string "blah"
is actually still in memory, but the label someString
doesn't reference that piece of information, it references the memory address of the null object(again, details). We need a way to specify to the computer "you know the [whateverSize] piece of memory I claimed starting at [whateverAddress]? Well I'm done with it now so somebody else can use that piece of memory". Gabage collection is an automatic process for reclaiming memory that you've claimed without having to worry about it yourself. In languages without garbage collection, new
has a complement keyword that specifically frees the memory associated to an object [3], but ActionScript doesn't have that; you just take a piece of memory and forget about it.
Somewhere along the lines, you may have created another variable and referenced that piece of data, var someOtherString:String = someString;
, so we can't just say "ok, the label someString
is gone, so let's get rid of the data that it references", because we don't know for sure that someString
is the only reference to that data. The method in which this is done varies between languages and garbage collection systems, but the basic deal in ActionScript is this: every now and then (especially if Flash is currently taking up a lot of memory), the garbage collector looks at all of the objects in the current SWF and finds all of the objects that don't have any reference [4]. So for our previous example, if someString
was the only thing that referenced the string "blah"
and someString
goes out of scope, then "blah"
isn't associated to any label and is therefore totally unreachable by Flash. The next time the garbage collector runs, it will find that and then report back to the system that it's done with that piece of memory.
Now, the specific details of your particular problem would be hard to say without looking at the source, but I can tell you that one of the things that often causes problems is event listeners. Sometimes you might create a function and add it as an event listener. Now the event itself has a reference to that function [5], so if the function goes out of scope, there's still a reference to it and the function does not get picked up by the garbage collector (remember, functions are objects in ActionScript). You can either remove event handler manually by calling removeEventListener (I wouldn't recommend it), or set the useWeakReference
parameter in you calls to addEventListener() to true
. A weak reference is not recognized by the garbage collector, so setting useWeakReference
to true
prevents the situation where you have a function that should be picked up by the garbage collector, but it doesn't because someone is referencing it as an event listener. Judging by the sheer number of mouseEvent listeners in your project, this could be the culprit. If you have Flex Builder, you can use the profiler to see how many method closures you have; if they're going up and never coming down, that's probably your problem.
[1]: Keep in mind that this also applies to situations where you create an object without using the new
keyword, like if you were to write var exampleInt:int = 5;
.
[2]: I chose uint because all uints are the same size, so I can say with confidence that I know it will be four bytes. Strings are different; they take up an amount of memory proportional to the number of characters they contain, so it would be a little more ambiguous to use String for both examples.
[3]: The ActionScript keyword delete
is not for this purpose, so don't try to use it in this way, even though that would make perfect logical sense and it would be very useful.
[4]: Flash uses a mark-and-sweep style strategy, the more specific details of which can be read here.
[5]: Actually, that's a boldface lie because the addEventListener method uses closures, but I have a pretty weak understanding of that to begin with so I can't really boil it down into normal person English.