Following my post yesterday about the addition of Loader.unloadAndStop to the Flash Player 10 API, I chatted with Werner Sharp, who is one of the Adobe engineers that worked on the feature (and an all round good guy). Following that discussion, I thought it would be helpful to post a summary of what I know about it, and disseminate some of the information Werner provided.
The unloadAndStop method was added in response to challenges ActionScript developers were facing with halting loaded SWF content, and removing it from memory. These issues were detailed in an article I posted in early April titled "Failure to Unload: Flash Player 9's Dirty Secret".
This API addition is not a magic bullet for solving all of the listed problems. What it does do, is attempt to prepare the loaded content for collection, and then hint to the Garbage Collector that it should initiate a collection pass. You can prevent the latter by passing false as the first parameter. It is still easy to get a SWF stuck in memory, but it is much harder to do accidentally.
Here is the list of things that unloadAndStop does to prepare loaded SWFs for collection:
- Stops all MovieClips
- Stops all sounds playing/streaming
- Stop/removes all Timer objects
- Remove all global listeners for enterFrame, exitFrame, frameconstructed, activate, deactivate
- Remove all stage listeners that have been created by the child.
- Closes all NetConnection/NetStream
- Video.attachNetStream/attachCamera(0)
- Microphone.setLoopback(0)
- Removes AS3 fonts from the global font table
- Stops sockets, xmlsockets, filereference downloads, other downloading objects (grandchildren SWF), etc.
- Frees bitmap related to cacheAsBitmap/filter, etc.
Note that all of the above are run recursively, so they will also apply to any nested children, including other loaded SWFs.
There have been a few early questions about unloadAndStop that I will try to answer:
Why wasn't this functionality just built into the unload method?
There are a couple good reasons for this. The first is backwards compatibility. This is a pretty major change in real functionality, if not expected functionality, and changing it could break a lot of content. This is also a very invasive function, and could have weird effects in some circumstances. For instance, if you loaded a SWF, made a reference to a child of that SWF, called unloadAndStop, then reparented that child into your main application things could get weird because that child DisplayObject has already been "stopped".
What types of things will keep the SWF in memory?
This API does not null external references to your SWF, or to elements in the SWF - doing so would be very processor intensive in large projects. As such, any hard references to the SWF or objects within it will prevent collection. For example, if your main application were to reference a movie clip in the loaded SWF such as:
var myFunClip:MovieClip = myLoader.content.funClip;
You can also do this inadvertently with events. unloadAndStop will remove listeners that the loaded SWF created on the stage (for listening to MOUSE_MOVE events, for example), but not in other locations. Something as simple as the following code in your SWFs main timeline can prevent it from unloading, because it will create a hard reference back to it:
parent.parent.addEventListener(Event.CHANGE,myFunction);
As you can see, unloadAndStop isn't perfect, but in conjunction with fixes for the bugs I mentioned in my article, it's a solid step in the right direction. That doesn't mean I'm going to stop pushing for content sandboxing and explicit unloading though. :)

Comments (39)
I know you used it as a simple example, but we would never use 'parent.parent.addEventListener(Event.CHANGE,myFunction);', wouldn't we? Very bad OOP practice that asks for problems.
Posted by: loeribas at July 5, 2008 02:24 AMBut it's ok you make us aware of these kind of memory householding things.
URL: http://arievanboxel.nl
Really good news yes, we are heading in the right direction :)
Posted by: Thibault Imbert at July 5, 2008 05:13 AMURL: http://www.bytearray.org
loeribas,
Yes, the example would definitely be an example of poor OOP architecture. Of course, that doesn't stop some people from doing it. It's also an example of bad practice because it doesn't use weak references for the listener - the following simple change to that line of code would ensure it did not prevent collection:
Posted by: Grant Skinner at July 5, 2008 10:45 AMparent.parent.addEventListener(Event.CHANGE,myFunction,false,0,true);
More info:
http://www.gskinner.com/blog/archives/2006/07/as3_weakly_refe.html
URL: http://gskinner.com/blog/
Hi Grant,
Great info as always.
Just wanted to ask, your Janitor class, does it do the same thing as the new unloadAndStop?
Thanks
Posted by: H Archer at July 5, 2008 06:21 PMURL:
Hi Grant,
first of all thank you so much on enlightening us on the neccessary topic of GarbageCollection.
Now, just like H.Archer above, I do have questions about your Janitor: I do not find any documentation on how to implement it into my sourcecode other than page 32 of your flash in http://gskinner.com/talks/resource-management/ :
++++++++++++++++++++++++++++++++++++++++++++++
import com.gskinner.utils.Janitor ;
var scruffy = new Janitor(this);
scruffy.addSoundChannel(sndChannel);
scruffy.addEventLstener(obj,"type",handler);
scruffy.addConnection(myLoader);
scruffy.addTimer(myTimer);
scruffy.addInterval(timerID);
scruffy.addDisposable(myBmpData);
scruffy.cleanUp();
+++++++++++++++++++++++++++++++++++++++++++++
1.) Now my first problem is that I instantly get the errors that scruffy would be undefined.
2.) Next I do not exactly understand this example in terms of declaration: Do I have to declare my arrays, objects, listeners etc first and then let them run through the scruffy Janitor, or is that addInterval... already a declaration ?
3. Does the Janitor Class replace all necesities for me to use weak references and your other utilities ?
I really would apprecciate a tiny, but complete example containing all your classes like the StageStatusNotifier, I definately want to implement your code into my FlexProject.
Thank you very much !
Posted by: Thilo at July 6, 2008 12:03 PMURL: http://CyMeP.com
Grant, thanks for posting this and your previous posts about this general problem.
The other way a SWF can be locked in memory is if the parent SWF reaches into the child and attaches listeners. Flex's FocusManager can do this and does not uses weak references.
For anyone reading, please test this API if possible with the latest Flash player build and report any findings. We've tried hard to get the issue resolved for well formed applications that do common things like have timers or stage listeners or enterframe listeners. Any feedback on the new API is appreciated.
Werner Sharp
Posted by: Werner Sharp at July 7, 2008 02:18 PMFlash Player Engineering
URL: http://www.adobe.com
Hey Grant. Long time reader, first time commenter.
One big problem I have with external content is if you load an external swf which has a doc class with some getters that return a new instance of a display object that is contained in that (external) swf's library. (the main reason for this method is ease for artists to created content.)
The second you add this swf to the parent swf's display list and keep it there for longer than 1-2 frames, remove it from the display list, that swf will NEVER get garbage collected in Flash 9. No listeners have been applied, the loader was nulled, load events removed immediately... so I am a loss on that issue. ( my 'solution' is to keep each loaded swf in ram so I can call new instances of the library content I am looking for. It sucks but it keeps from having 60 some odd copies of 1 swf in ram)
Hopefully the above was clear enough to understand ^_^
Posted by: Louis Tovar at July 7, 2008 04:58 PMURL: http://deadlock32.newgrounds.com
I was a little confused by Werner's post, so I contacted him for clarification. Listening to an event on a loaded child will not prevent it from properly unloading.
He was trying to point out that parent content can also create situations where the child is not unloaded. For example, if a parent reaches into a child and adds a listener back to itself. Not a good practice of course, but worth being aware of.
// in the parent:
Posted by: Grant Skinner at July 7, 2008 05:09 PMthis.addEventListener(Event.CHANGE, myLoader.content.childFunction);
URL: http://gskinner.com/blog/
For the most part, it looks like this should reduce weight on the proc until the gc makes a pass. I wonder though, does it have any scope limitations or Objects that the method does not access? I'm thinking Arrays and anonymous Objects... Does the cost of running these operations at any point become greater than the cost of hinting the gc to make a pass? Does this hinting at the gc have the same effect as System.gc()?
I have just one more question: in the case of an object in the loaded swf listening to events of an object in the parent domain, the object in the loaded swf is referenced because the object being listened to in the parent domain has added the object in the loaded swf to its listener list - is this correct?
Thank you.
Posted by: Melih Elibol at July 17, 2008 12:51 AMURL: http://blog.computerelibol.com
Louis Tovar,
You said your SWF had getter methods for returning an instance of a DisplayObject, perhaps you forgot to remove that instance from the display list? The SWF won't get GC'd until all objects you retrieved from it's library have been removed from memory.
Posted by: Andres A at August 6, 2008 01:33 AMURL:
I'm trying out unloadAndStop methods on a little bigger project, but loaded swfs are still not unloaded. I know, unloadAndStop is just "attempting" to prepare loaded SWF for unloading. But I guess what we really need is some method that "force" loaded SWF to unload no matter what.
Do you know any good way how to observe and find where in application we have memory leaks?
Do you have any info if in PARENT movie which is compiled for FP10 you are using unloadAndStop but loaded SWFs are compiled for FP9? Does it still works?
Thx
Grega
P.S.: Your janitor class is great !!!
Posted by: Gregor Cepek at August 15, 2008 04:51 PMURL:
@loeribas: Sometimes you want to listen for events on the main application object. e.g. the "resize" event. In that case you'll end up with a reference from the main application to the loaded application, unless you use a weak reference (which you should).
@Werner Sharp: Flex's FocusManager does hold references to objects inside the loaded SWF, but it releases the references when the objects are taken off stage; so that shouldn't be a concern.
Posted by: Manish Jethani at August 18, 2008 05:21 PMURL: http://manishjethani.com/
Hello: Im having trouble with a movie im working on
Trying to unload a swf file loaded in an empty movie clip on the main timeline. when i click the button its unloads the movie but just goes to a black screen, i want it to resume the main movie..
any ideas??
on (rollOver) {
this.gotoAndPlay("s1");
}
on (releaseOutside, rollOut) {
this.gotoAndPlay("s2");
}
on (release) {
_root.loadMovie("pm.swf","blankmovie");
}
and to unload..
on(rollOver) {
if(_root.link>num) {
this.gotoAndPlay("s1");
}
}
on(rollOut, releaseOutside) {
Posted by: Mike Connolly at October 27, 2008 03:56 AMif(_root.link>num) {
this.gotoAndPlay("s2");
}
}
on (release) {
if(_root.link>num and _root.animation==1) {
_root.animation=0;
_root.link_prev=_root.link;
_parent["item"+_root.link].gotoAndPlay("s2");
_root.link=num;
_root.slide_contol_movs(668.3);
_root.pics_blur_alpha(0);
//_root.pics_blur.pic.gotoAndStop("s0");
}
_root.unloadMovie("pm.swf","blankmovie");
_root.gotoAndPlay("s2");
}
URL: http://www.miconn.ca
Mike - my AS2 is getting a bit rusty, but as I recall loadMovie loads a clip into the clip that you call it on. The second parameter specifies whether to use GET or POST to send variables. Likewise unloadMovie does not take any parameters, and unloads the movie you are calling it on.
So your code is replacing root with the loaded content, then unloading that content (and hence root).
You will likely want to look up loadMovie, unloadMovie, and createEmptyMovieClip in the AS2 docs.
Cheers.
Posted by: Grant Skinner at October 27, 2008 08:52 AMURL: http://gskinner.com/blog/
I don't know if this qualifies as a bug, but it's worth pointing out. If you're publishing to a projector, you still need to enable SWF export and change the Flash Player to version 10. You can then disable SWF export again.
Otherwise, the compiler complains about an undefined method unloadAndStop.
Posted by: Ed Jackson at November 11, 2008 10:06 AMURL:
hi friend,
i try to assign a multiple SWF's Frames into single slider. when i drag and change on the slider . it should play smoothly the current swf's frame. whether is it possible in the flash?.
please send me some samples
Thanks and Regards
Posted by: Karthick Raj.S at December 5, 2008 09:44 PMKarthick Raj.S
URL:
hi friend
i am waiting for your reply
Thanks and Regards
Posted by: Karthick raj at December 5, 2008 09:45 PMKarthick Raj.S
URL:
hi,
i try to assign a multiple SWF's Frames into single slider. when i drag and change on the slider . It should play according the current swf's frame. whether is it possible in the flash.Please help me....
Thanks and Regards,
Posted by: khan at December 5, 2008 09:47 PMkhan
URL:
Hi,
Does adobe have remove this function or at least desactivate it ?
Because it doesn't work any more with the last version of Flash Player (10,0,12,36) !?
I don't have any error, but the content isn't unload, as it was in previous version ?
To test, I do something ugly, like playing sound unloadAndStop, and the sound is still playing ?
Any idea ?
Posted by: Hugues BERNET-ROLLANDE at February 10, 2009 05:01 AMURL:
Hi
I'm creating AIR application in Flash CS3. In That application, I was loaded some swf and unloaded the swf. But the Memory could not clear.
So I prefer to go with unloadAndStop method in Flash CS4 and FP 10 Features. The Problem is All(main and Loaded) swf and supporting classes created in Flash CS3.
If i compile in Flash CS4 it shows error: The Error is 1061: Call to a possibly undefined method unloadAndStop through a reference with static type flash.display:Loader.
I saved the main swf as a Flash CS4. After that also the same error shows. What can i do for it? Any Sttings changes?
Thanks
Posted by: krk at February 16, 2009 07:56 PM-krk
URL:
Hi
UnloadAndStop method is working now. The problem solved by "Adobe AIR 1.5 Update for Flash CS4". But, there is know different in memory problem.
Thanks
Posted by: krk at February 17, 2009 06:39 PM-krk.
URL:
Anybody know what I am supposed to do if I use CS3, I can't publish to FP10 and don't want to pay the overpriced UK upgrade to CS4. This effectively renders all my work flawed. Tried asking adobe but they got defensive and cut me off. With high prices, large bugs and rude support I'm tempted towards the evil of all evils, microsoft silverlight :-(.
Posted by: Gareth at March 9, 2009 08:28 AMURL:
I happened to come across an unfortunate bug that I haven't seen listed anywhere. I'm currently using Flex to load external SWFS created by Flash CS4, and if these SWFS happen to contain an instance of the Button component, these SWFS can never get unloaded. I have done very strict testing in several environments, and the result is always the same. When you remove the Button instance from the external SWF (this instance was placed on the stage during design time), the SWF will unload. I have not tried it with other components. Just a heads up.
Posted by: ben at April 23, 2009 12:20 PMURL: http://www.darkbluemorning.com
I'm getting the same issue as Ben (April 23, 2009 12:20 PM) only purely in flash, which suggests its not a flex issue.
I also checked with textInput, textArea, comboBox and radioButton UI components, simply dropped on stage in the external loaded swf, with no other code or settings applied therein.
They all seem to get stuck in memory after unloadandstop.
My contentmanager app loads swf's into a new Loader() with a new ApplicationDomain() and new LoadContext(), all of which are created for each load referenced with dynamic unique varaible names held in an object, so they can be completly
nulled and deleted with the unloadandstop.
This is working perfectly with other swfs.
After a quick scan through the base UIcomponent class it seems it may be related to the focus and/or style manager classes they use, as they look like they store refernces.
Unfortuantly i've had no luck proving that as i can't seem to clear either manager class externally (can't figure much out inside the UI classes either!).
Calling stage.focus=stage from my contentmanager before calling unloadAndStop() made no difference,
but I have noticed that if you load then unloadandstop without ever adding the loaded swf to the display list there is no memory leak, the file is correctly disposed of.
Ok a little useless in itself as you need to see your loaded content, but as the UIcomponent class makes use of the ADDED_TO_STAGE event there's a clue there at least!
Any ideas?
Posted by: andy at April 28, 2009 09:32 AMURL:
THANKS SO MUCH ;-)
Posted by: Renaud at May 27, 2009 03:10 PMURL: http://www.110plom.com
I am looking to finish
Posted by: jeries at June 10, 2009 04:06 PMURL: http://hgtyuj
Thank you for the important information you introduced.
actually i have a problem when i tried to use this function is as3 it produced an error "1061: Call to a possibly undefined method unloadAndStop through a reference with static type flash.display:Loader." which i could not fix it ..
please if you can help me ,send me on my email
mohammed.fci86@gmail.com
Thank you.
Posted by: mohammed at July 7, 2009 05:33 AMURL:
I have a question. I am loading in lets say at frame 12 I want to unload and not see the swf I loaded at frame 14 .. can't figure it out. Here is how I load the swf
stop();
import com.jeroenwijering.events.*;
import com.jeroenwijering.player.*;
import com.jeroenwijering.plugins.*;
import com.jeroenwijering.utils.Configger;
import flash.display.MovieClip;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.net.URLRequest;
var view:Object;
var videoPlayer = new Loader();
videoPlayer.contentLoaderInfo.addEventListener(Event.COMPLETE, videoLoaded);
videoPlayer.load(new URLRequest('DemoPlayer/player-licensed.swf?volume=100&image=image.jpg&icons=false'));
function videoLoaded( evt:Event ):void {
var ply = evt.target.content;
ply.addEventListener('READY',playerReady);
// customize flashvars via the ply.config object
ply.config.resizing = false; // leave this for custom width, height, x, and y
ply.config.file = 'my.mp3';
ply.config.height = 295;
ply.config.width = 622;
ply.config.skin = 'DemoPlayer/simple2.swf';
// position player on the stage
videoPlayer.x = 1;
videoPlayer.y = 19;
addChild(videoPlayer);
}
function playerReady(evt:Event=null) {
view = evt.target.view;
view.sendEvent(ViewEvent.PLAY);
view.sendEvent(ViewEvent.LOAD,evt.target.config);
};
Can anyone help me with unload the child?
Posted by: Jim at July 7, 2009 02:44 PMURL:
I have loaded a swf lets say at frame 12, but I want to unload and not see it at say frame 14. Here is how i loaded it. Can anyone help me unload it?
stop();
import com.jeroenwijering.events.*;
import com.jeroenwijering.player.*;
import com.jeroenwijering.plugins.*;
import com.jeroenwijering.utils.Configger;
import flash.display.MovieClip;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.net.URLRequest;
var view:Object;
var videoPlayer = new Loader();
videoPlayer.contentLoaderInfo.addEventListener(Event.COMPLETE, videoLoaded);
videoPlayer.load(new URLRequest(’DemoPlayer/player-licensed.swf?volume=100&image=image.jpg&icons=false’));
function videoLoaded( evt:Event ):void {
var ply = evt.target.content;
ply.addEventListener(’READY’,playerReady);
// customize flashvars via the ply.config object
ply.config.resizing = false; // leave this for custom width, height, x, and y
ply.config.file = ‘my.mp3′;
ply.config.height = 295;
ply.config.width = 622;
ply.config.skin = ‘DemoPlayer/simple2.swf’;
// position player on the stage
videoPlayer.x = 1;
videoPlayer.y = 19;
addChild(videoPlayer);
}
function playerReady(evt:Event=null) {
view = evt.target.view;
view.sendEvent(ViewEvent.PLAY);
view.sendEvent(ViewEvent.LOAD,evt.target.config);
};
Thanks in advance.
Posted by: Jim at July 7, 2009 02:49 PMURL:
Sorry about the duplicate post. My browser crashed .. didn't think it went through.
Posted by: Jim at July 7, 2009 03:32 PMURL:
Hi
I am seeing the same issue as Ben and Andy. I am loading a .swf (flash 10) into a new ApplicationDomain that contains a list component. This never gets released from memory even with the unloadAndStop method. When the list component is not in the swf it unloads as expected. I am having the same problem with the textarea component. Need to find a solution to this quick. I can't get around using seperate ApplicationDomains and I would hate to have to create my own slimmed down components.
Jonathan
Posted by: Jonathan at July 16, 2009 07:04 PMURL:
I am seeing the same issue as Andy. Even with unloadAndStop I can't properly unload a movie in a seperate application domain when it includes a flash component. Any suggestions?
Posted by: Jonathan at July 17, 2009 09:44 AMURL:
I think Adobe really dropped the ball here. I am still looking for a good reason why a movie clip would continue to play music when it was unloaded.
It's just bad and it will keep people asking questions here, or developers would just choose not to load third party SWFs.
The quality of their products is degrading as they try to change them...
Posted by: vanbcgunner at August 12, 2009 06:32 PMURL:
Hey,
Some of the posters where saying that using
'parent.parent.addEventListener(Event.CHANGE,myFunction);',
Is bad practice.
This is what I do :(
What way should you do it?
Posted by: dub at August 21, 2009 04:47 AMURL:
Just wondering if anybody else shares my point of view. Putting an unloadAndStop method on the Loader class, but not making it accessible from the UILoader class is really stupid.
Posted by: Tecsi Aron at September 3, 2009 05:15 AMURL:
I just tried to used Loader.unloadAndStop today. it works in the standalone player but not in the browser.
this traces out true in the desktop player
trace("has Loader.unloadAndStop()",(new Loader()).hasOwnProperty("unloadAndStop"));
but false in the browser what gives?!!!
tested under OSX 10.5.8 FF and Safari with Flash player 10.0.12 and 10.0.38
Posted by: guojian at October 23, 2009 07:39 AMURL:
duh!
Posted by: guojian at October 23, 2009 08:32 AMmy swf was being loaded into a flash 9 swf!!! just wasted 2 hours :)
URL:
I think the question is "Why wasn't this built into the unload method ORIGINALLY". Of course, after they screwed it up, adding it later would change it's behavior. So why wasn't it there in the first place? That would be a very interesting answer.
Posted by: Triynko at October 26, 2009 10:07 PMURL:
Fought with this for days... then saw this... thanks! I was using BulkLoader to load things but unloading things (remove, removeAll, unload) wouldn't remove the damn swf. But I'm using FP10. I think Adobe should add an annex to their headquarters called the crying room so all of us poor bastards could go there for a free round after this kind of thing.
Posted by: Sam Wilson at November 11, 2009 01:28 PMURL: http://www.storypixel.com