Additional Information on Loader.unloadAndStop

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. 🙂

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

45 Comments

  1. 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.

    But it’s ok you make us aware of these kind of memory householding things.

  2. Really good news yes, we are heading in the right direction 🙂

  3. 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:

    parent.parent.addEventListener(Event.CHANGE,myFunction,false,0,true);

    More info:

    http://www.gskinner.com/blog/archives/2006/07/as3_weakly_refe.html

  4. Hi Grant,

    Great info as always.

    Just wanted to ask, your Janitor class, does it do the same thing as the new unloadAndStop?

    Thanks

  5. 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 !

  6. 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

    Flash Player Engineering

  7. 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 ^_^

  8. 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:

    this.addEventListener(Event.CHANGE, myLoader.content.childFunction);

  9. 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.

  10. 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.

  11. 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 !!!

  12. @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.

  13. 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) {

    if(_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”);

    }

  14. 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.

  15. 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.

  16. 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

    Karthick Raj.S

  17. hi friend

    i am waiting for your reply

    Thanks and Regards

    Karthick Raj.S

  18. 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,

    khan

  19. Hugues BERNET-ROLLANDE February 10, 2009 at 5:01am

    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 ?

  20. 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

    -krk

  21. 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

    -krk.

  22. 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 :-(.

  23. 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.

  24. 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?

  25. THANKS SO MUCH 😉

  26. I am looking to finish

  27. 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.

  28. 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?

  29. 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.

  30. Sorry about the duplicate post. My browser crashed .. didn’t think it went through.

  31. 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

  32. 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?

  33. 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…

  34. 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?

  35. 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.

  36. 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

  37. duh!

    my swf was being loaded into a flash 9 swf!!! just wasted 2 hours 🙂

  38. 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.

  39. 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.

  40. Just noticed that it looks as if gtween doesn’t get removed when you use unloadAndStop. I use GTween as timer in one of my projects, (partially because I used to not use timer at all because I wasn’t GC’ing correctly… (duh) and found taht timers hung around) but when I run unloadAndStop now, any gtween still running will continue until finished. Now I am back to timers, and much happier that I know how to stop the buggers correctly! Thanks for the post.

  41. I experimented quite abit with unloadAndStop and just decided its just another half-ass attempt at doing what we need it to do.

    It does a little more than unload did, but not nearly enough.

    Grant’s idea of putting the child SWF in it’s own sandbox with it’s own stage is a good one.

    Here’s some more info:

    I have a flash app I test with using just flash and also using C++ controlling flash.

    What I see with unloadAndStop is it just does not clean up and will leave sockets open. Not sure what it does with the sockets, but they are not released. I can monitor this from my server and server thinks the sockets are still open until it times them out.

    But to go further, even if I init flash from C++ with a brand new SWF (not a child), it will leave the sockets open. No matter what I have tried with trying to cleanup flash from C++ it does not cleanup.

    The only solution from C++ I have found is to completely destroy the flash control and finally we have complete cleanup. Of course this is not available directly in flash, but just goes to show you how deep this problem goes. Also this a radical thing to have to do.

    It should be clear that we want to load SWF’s into a parent SWF and we may not have complete control over the child SWF. They can be all over the place in what they do and designed by people who are not well versed in programming. So the parent SWF needs to be protected from them and they need to be cleaned up completely when we need them to be.

    I don’t want to hear how hard it is to do blah blah, it’s just a stupid machine that will do what you tell it to do if programmed correctly. Sounds to me like the computer is programming the programmers rather than the other way around.

    This is not brain science Adobe.

    Don

  42. I work at a large site that aggregates Flash games.

    I am tasked with building a Menu in Flash that loads games from a wide variety of different developers . . . some in AS2, some in AS3, etc.

    Despite loading each SWF into its own application domain and despite calling unloadAndStop() on the loader instance . . . I am getting a lot of games that seem to live on in the background, making sounds, making traces, and throwing ActionScript errors.

    The solution that I know will work is to call a javascript to load the SWF in a div tag (I Frame) in the browser (no Loader object). That seems to be the only way to achieve complete encapsulation in AS3. For many of you, this is the solution you should look at . . . assuming your project is for a browser. You’ll probably want to set your WMode to “opaque” for best results, but you can load one SWF right on top of another with this technique and few (if any) will ever know that it’s actually the browser that is compositing them. There is a little massaging you’ll have to do in IE7 to keep them lined up correctly. Have fun with that.

    That said . . . this technique is off-limits to me in my current assignment. I must load each game with a Loader object in AS3. Does anybody have any ideas for how I could do this? Or is this task just plain impossible in AS3 given that I have no control over the wide variety of SWFs from other developers that I will be loading . . . ?

    Thanks . . . and good luck to those of you who are struggling with this problem.

    And thanks to the good folks at Adobe for all of their hard work making the Flash platform so freakin’ awesome.

  43. Hi all.

    I’ve read this article and the previous one about this subject and first of all thanks for your work and for having shared with “us” all of this points.

    We (our company) are facing a huge performance issue in our AIR application.
    The application is designed to analyse an external swf and tell the user if it fits some requirements (size, length, and so on).
    So our application load the external swf (wich can be third party ( T_T ) and try to access some of the content properties, then it tries to unloadandstop this swf.
    We’re experiencing this issue : old swf, especially one with only timer or code (no time line), are still running in the background after and unloadandstop() call.
    I let you imagine with 30 or 40 swf running like this in the background, CPU and memory both disagrees with the user dream of having a smooth and peacefull use of our application.
    We simply can’t tell the client “it’s because of bad / poor swf” because it’s what he pays for : having a meta application which “verify” other swf.
    How to access external swf properties without loading the whole swf ?
    How to force unloading “old” external swf loaded ?

    Regards.

  44. This problem persists in Flex Mobile. As cool as the Flex Mobile platform generally is, I’ve had a few frustrations with it (sizing things and having consistent results between emulator and device are a couple of examples). I overcame them all to finally have to stare down this one. I have tried everything I can think of to get the SWF’s that are loaded in one view to dispose when a new view replaces the current view on the stack. It just won’t happen. If anyone knows how to force an SWF to die in Flex Mobile, I would love to hear about it. Since I can’t get the SWF’s to unload as I move along the view stack, my app gets slower and slower until it crashes. I load via SWFLoader and try to dispose by removing all event listeners and calling SWFLoader.unloadAndStop(). It’s to no avail.

  45. Mr. G.Skinner, your classes does not remove any of my movie clips!
    I`ve tested your classes and demo versions.It works only for your .SWF-s! I can`s unload external movies with your program :(.
    My external movie clips contains: Timers and Sound.
    Any help?

Comments are closed.