Failure to Unload: Flash Player 9’s Dirty Secret

Update: Adobe has added the Loader.unloadAndStop method to Flash player 10 to address some of the issues outlined in this article. You can find more details on this feature in my article “Additional Information on Loader.unloadAndStop“.


Flash Player 9 has a very dirty secret. It doesn’t even try hide this dirty secret, but it’s still not that widely known. You see, Flash Player has severe problems with separation anxiety – once it’s loaded some content, it has a really hard time ever letting it go. Technically speaking, it is extremely difficult to make Flash Player 9 unload ActionScript 3 content.

In this article, I’ll take an in-depth look at the issue, it’s implications, suggestions for addressing the problem in the player, and some workarounds for the time being. If this issue seems like it will impact your projects, I’d strongly encourage you to read through the article and educate yourself, then use the link at the end of the article to provide Adobe with feedback on it. Likewise, I would encourage you to share this issue with other developers, both to help spread awareness of the issue, and to give them the opportunity to also provide feedback to the Flash Player team. I see this as one of the most critical issues that should be solved in Flash Player 10, and the more people raise it as an issue with Adobe, the more likely it is to be addressed.


In my opinion, this issue breaks down into three problems: A major player bug, content sandboxing, and explicit unload functionality. Note that these issues affect content created with both Flex 2/3 and Flash CS3.

Background

First, a little bit of info on the AVM2 garbage collector for those who haven’t read my previous articles about resource management in player 9. With ActionScript 2 content, calling MovieClip.unloadMovie() explicitly removes the contents of a MovieClip. This meant that your loaded content would immediately stop executing, and be removed from memory.

In AS3, calling Loader.unload() simply removes the reference to the loaded movie. If any other references exist to the loaded content, it will not be unloaded. Even when all references are removed, it only frees the content for collection by the garbage collector at some indeterminate point in the future. This means that even if everything worked as expected the loaded content will continue to execute, and remain in memory for an indeterminate amount of time after you unload it. This is problematic in many ways, but it is made worse by a bug in the player.

Flash Player 9 Bug

Flash Player 9 has a critical bug that prevents unloading loaded SWFs that have any active ENTER_FRAME or TIMER event listeners. This occurs regardless of whether these listeners are all within the scope of the loaded SWF, or even if they all use weak references. This also affect timeline code written in Flash authoring – if you have any code in your timeline, it will not be possible to unload that SWF.

Content Sandboxing

AS3 lacks any support for explicit content sandboxing. By this, I am referring the ability for a developer to load a SWF into a sandbox, so that the loaded content can’t reach back into the loading application. This would be a very useful for a number of reasons, including loading third party modules or plug-ins without having to worry about them messing with things in your application. More important to this article though are the implications on unloading loaded content.

Firstly, content sandboxing would allow a developer to prevent a loaded SWF from adding listeners outside of its scope. This is important, because developers rely on stage events in AS3 for notification of things like global mouse movements, and key presses, but creating a stage listener from a loaded SWF will prevent it from ever being unloaded (unless it uses weak referencing). This is because addEventListener creates a reference back to the listener from the event dispatcher (in this case, the stage). This means that your content might never unload, and it means that third party content can (intentionally or not) prevent itself being unloaded by simply adding a stage listener.

Secondly, content sandboxing would allow the player to keep loaded content in a nice clean package, which I imagine would make explicit unloading possible.

Explicit Unloading

As outlined in the background section, there is no way to explicitly unload loaded SWFs in AS3, which was very simple in AS2. There is a good reason for this – content can be referenced, instantiated, and re-parented across SWF boundaries in ActionScript 3. This makes unloading content much more complicated than it was in ActionScript 2. Still, the lack of this capability is a major downgrade from AS2, and makes some types of projects nigh on impossible.

I believe that content sandboxing would help address this issue, making it much easier to remove loaded content. Adobe could restrict the ability to explicitly unload SWFs to sandboxed content. For most applications that rely on loading and unloading content dynamically (galleries, for example) this would be an adequate solution.

Implications

These issues have some major implications, that affect three types of projects in particular:

  1. Gallery or portfolio projects. Some of you may have noticed that incomplet.org [Moved to incomplet.gskinner.com] stagnated as soon as AS3 was released. This is because it’s virtually impossible to create a site like incomplet.org in AS3. Because loaded content cannot be easily unloaded, it would mean that experiments would continue to run in the background after users clicked off of them. The whole site would slow to a crawl, and eventually crash. Not good. This is also the reason that in my upcoming FitC talk, I will likely have to resort to running my demos externally, instead of dynamically loading them and displaying them in the slides. Most likely this will prevent me from sharing my slides online as well, which is something I have been doing for years.

  2. Applications that load third party content. Any application that loads plug-ins, modules, or content from third parties is currently very problematic to develop. In order to do so, each piece of content must adhere to a strict coding standard, and expose a common API for deactivating the content. I feel there is also a bit of a security issue here, because the third party content can add a stage listener to prevent itself from being unloaded, then monitor all key and mouse interactions.

  3. Advertising. It’s currently impossible to safely embed AS3 based advertising into an AS3 based site. Most advertising uses timeline code, enterframe listeners, and timers, so if you have rotating banner ads loading into your Flash site, old banners will never stop executing or be removed from memory. Worse yet, if the banners are being served from within your domain, they pose a major security risk, as outlined in #2 above.

Part of what makes this so important is that it entails a reduction of capability from player 8 and AS2. It’s also weird messaging for Adobe, that Flash is awesome for building online experiences, and it’s great for creating online advertising, but it isn’t suitable for developing online experiences with advertising. It will also become increasing important as Flash / Flex sites become more modular, and with increased use of third party content and embedded ads.

Proposal for the Flash Player

At a minimum, I’d like to see the player bug resolved as soon as possible. I also don’t think it’s unreasonable to hope for some support for content sandboxing and explicit unloading for player 10. The API already has nice hooks for it.

To enable content sandboxing, Adobe could simply extend SecurityDomain to work similarly to ApplicationDomain, allowing developers to put loaded content into a new security domain, so that it cannot access the loading SWF. The nice things about this is that it wouldn’t require any new APIs, it would mirror an existing model, and there are already mechanism for dealing with this (this is essentially what happens when you load a SWF from another domain). We also already have a nice model for communicating with sandboxed content with childSandboxBridge and sharedEvents.

For explicit unloads, I would suggest simply adding a Loader.dispose() or Loader.remove() method. This could work just with sandboxed content, and throw an error if the content cannot be removed.

These changes wouldn’t directly solve every issue, but they would give developers the tools to address all the major problems themselves.

Work-Arounds and Strategies

There are four main things you can do to address these issues now:

  1. Make sure that you are always removing timer and enterframe event listeners in content you may want to load into a larger application. Also, try to avoid stage listeners where possible, and remove them immediately when you are done with them.

  2. Expose a standard API in your SWFs that allows other SWFs to tell it to clean up and stop executing. This way, the loading application can call this method (within a try/catch block) before it unloads any content. I would suggest a .halt() method, backed by a listener for a “halt” event through sharedEvents.

  3. You can load content SWFs from a subdomain. This will place it into a security sandbox implicitly.

  4. Load content into a div layered over your main application. This isn’t a great option, but it addresses almost all of the issues.

Providing Feedback to the Player Team

If you’d like to provide feedback to the Flash Player team on this or other issues, you can do so at this URL:

http://www.adobe.com/bin/fp8betafeedback.cgi

The player team is a group of smart, dedicated people, who are genuinely interested in what you have to say. They read every submission they get from that form.

If you do contact them about this issue, feel free to point them to this page for the explanation, but also let them know how this issue might impact your work.

Grant Skinner

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

@gskinner

102 Comments

  1. Grant, thanks for bringing important issues like this up for the community. – William

  2. Always an excellent article Grant. I hope the flash player team could solve this issue for the next version.

    Regards.

  3. Very nicely put. We have been fighting these exact issues at my company for a while now. We run games that need to continue to run 24/7 for months. This is quite problematic with Flash’s minimal memory management options. Thanks for the article.

  4. Thank you for clear description of what is happening. We’ve been plagued by Flash’s grabby behavior in Flash Player 9 for quite a while. In our loaded mini-games we do what you suggested in #2 above – expose an API that encourages good behavior and cleanup.

  5. Wait, I am confused. I thought you COULD specify a securityDomain when loading a swf. Anything loaded to the null security domain couldn’t access your swf code.

  6. Arpit,

    Currently, SecurityDomain is only relevant to SWFs loaded cross domain, and they only give you two options:

    1) Load the SWF in it’s own domain

    2) Load the SWF as if it were in your domain

    I’m proposing extending the model to allow you to load SWFs from your own domain as though they were in a separate domain. This way you could isolate different SWFs in completely different security domains, or even put multiple SWFs in a shared (but separate) domain.

    Cheers.

  7. Grant,

    Well put. I’ve been voicing my opinion in mass on this subject. It’s so bad that for some large scale pieces, I don’t recommend clients use AS3 or convert to it. Take a site like Disney.com, with so much 3rd party content loaded in, it’s a sitting volcano. Another which has already been noted is a Game loader. The list goes on and on when you are building apps that deal with content you can’t completely control. It’s pretty scary because most people don’t understand the implications of it. I’ve voiced it before, but you have my support 10 fold on this one.

  8. Glad to hear I’m not the only one frustrated by this.

    Just to reiterate, if this is causing you problems now, or is likely to cause issues for you in the future, please do use the Flash Player feedback form linked above to tell the player team why this impacts you. They do read that feedback, and it really does have an effect on how they allocate resources for player development.

  9. We’re building a LMS in avm2 trying to leverage the ability to load avm1 and avm2 flash content (especially captivate) and the biggest headache in the development has been the flash content itself (which imo, shouldn’t be).

    Memory usage goes through the roof pretty fast, and theres no way for me to protect the application from the loaded content, let alone unload a swf with sound that is happy to continue playing long after the user has moved on, and I’ve unloaded(?) the content.

    I can only hope the player team can dedicate some time to it.

  10. This problem affects us pretty significantly as well – our core application is a movie editor with hundreds of different swfs representing different fx and transitions, all authored by our artists. These days, we simply don’t use the timeline in Blaze when authoring content – we have programmers go through and re-code the content the artists produce, with a manual destroy method where they explicitly free resources. There are some huge memory leaks in basic timeline operations even aside from the unloading issues. Adobe gave us the impression that they know about at least some of the issues but they won’t be fixed for Flash 9. In the meantime, our crappy workaround was writing a library that repeatedly attempts to stop the swf and recurses into all children attempting to stop them if they’re movieclips, keeping track of currentFrame on all the movieclips encountered during traversal until they’ve all stopped (why there’s no isPlaying method on MovieClip is beyond me). It often takes 2-3 frames to stop the SWF since they might be spawning new children in the process, but this eventually works.

    Before I wrote the library, they’d continue sucking CPU resources forever.

  11. Great article, Grant. This is definitely a huge deal that is causing all of us large amounts of frustration.

  12. Great article Grant. I’ve recently done a kids CD ROM game based on Flash and ensuring that unloading content did not cause problems took almost 10% of my time on the project. This is stuff that the client don’t want to pay for and that you just have to do (or the game will suck). Not very pleased to have to spend that extra time…

    I learned quite a bit about unloading and memory during the project (i.e. never have streaming sounds present in frame one of a timeline animation or they will become “ghost sounds”), but I really should not have to. Flash should “just work” without resorting to odd solutions.

    J

  13. Great article!

    You said: “For explicit unloads, I would suggest simply adding a Loader.dispose() or Loader.remove() method.”

    This might also be useful for DisplayObject (or even Object).

    Without it, programmers have to handle in-game dynamic content by reference counting, etc.. and it’s also prone to errors and also adds 10% time managing stuff that was well done in AS2.

    For example, in a game a room section edited by a level designer (or an animator) could contain an ENTER_FRAME (that’s a pretty common stuff in games ;-)).

    In such case, unloading this movieClip is useful, efficient, and doesn’t force the designer to learn memory-management stuff unrelated to the (more interesting, to my opinion) subject he’s dealing with (a monster, an AI, etc..)

  14. So that’s why! Right, this makes sense now, thanks for clarifying things Grant!

  15. Really thanks for sharing your knowledge, it helps a lot.

    Those behaviors make it very easy to leak in our applications. On top of that, the whole framework has a hug memory footprint. Take for instance Buzzword : after a few minutes, it takes more than 100Mo. M$ Word only amounts to 10Mo (and the feature set is quite different…)

    So far, that was not too problematic for a web application – a reload and it resets the memory. But for AIR, a desktop technology – thus meant to run much time-lengthier applications, that is a huge problem.

    Maybe it’s the same for other VM languages such as Java (but at least with Java leaks are much less frequent) but I really doubt we will see big applications moved to AIR…

    {Maz}

  16. Thanks for bringing this to light Grant. This is an issue to worry about, and one I hope gets addressed very soon, as it could affect the ability to convince clients to move to AS3. Personally, I’d rather not go back to AS2! I’ve sent my voice along and hope that others do too.

  17. Great article, I was wondering why the memory usage keeps increasing even if I “remove everything”.

  18. I had this exact problem… I have an experience site that suffers from this issue. I had to re-code loaderManagers 3 times, and then deal with stuff always being in RAM. unload is bogus and setting stuff to null is bogus, removing event listeners is bogus, garbage collection in flash is a skam.

    Why can’t we excplicitly tell a loaded object to die?!!

  19. This is a huge issue for our courseware runtime and course editor. Our clients love to use 3rd party animations that they bought or made-captivate for example- and it’s going to get harder to support it. Under AS2 i already fight with messy animation files, but this issue has slowed our move to AS3 in the runtime.

  20. One of our developers said that he noticed the same problem. Try setting the variable that you loaded the swf into to null.

  21. Elliot, while that is good practice, it does not affect any of the issues outlined. Please feel to read through the Background section above, and the linked Resource Management articles for more information on this.

  22. Thx a lot for the explanation ! Very instructive ! We had a lot of difficulty with with our website http://mtl12.com because of those problems.

  23. This is great information. Thanks.

    Have you posted this into the Flash Player JIRA yet?

    https://bugs.adobe.com/flashplayer/

  24. Hello Grant,

    About the Flash Player 9 Bug…

    You wrote “This also affect timeline code written in Flash authoring – if you have any code in your timeline, it will not be possible to unload that SWF.”

    I have a newbie question: when you say “timeline code”, do you mean also a simple “stop()” or not? (in fact also a “stop” is a line of code)

    I ask because I normally load external assets that do not contains code but only a few “stop()” and I was thinking that these assets were disposed when I remove them from the display list and set any pointer to them to null.

    Thanks in advance (and sorry for my english).

  25. Thanks for these useful informations! Are there any chance for a coming official whitepaper about these optimalization techniques and best practices?

    Most of the flash developers are affected about these things I think.

  26. There are a couple of memory releasing tips in this Ultrashock thread…

    http://www.ultrashock.com/forums/random-chat/failure-to-unload-flash-player-9s-dirty-secret-99237.html

    Getting a Loader to actually unload is easy enough to do but requires the LocalConnection GC hack.

  27. Si++,

    Sorry, but the information in that thread is incorrect, and even harmful.

    First, it is bad practice to use the LocalConnection hack in a real project (as mentioned in my original article on tools for resource management in AS3, which is most likely where Nutrox learned of it). I have to admit I debated sharing that technique, because I knew some people would misuse it, but it’s also hugely useful for testing GC issues.

    For your reference, here is the article:

    http://www.gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html

    Secondly, even if it was an ok practice, all the hack does is run the garbage collector, which suffers from the bug mentioned in this article, regardless of how you initiate it.

    It’s worth noting that all of the testing for this article was done using the LC hack, so I know for sure that it does not resolve any the issues.

    I wish there were easy answers to this one, but there isn’t.

  28. On the other hand, Nutrox’s ByteArray trick does work, and is quite interesting. Worth checking out. I might add that to the resource management tools article.

    myByteArray.length = 0;

    myByteArray = new ByteArray();

    // causes an immediate collection of the old byte array data.

  29. Great great info Grant, thanks much. Would you elaborate on the extent to which workaround #3 does (and doesn’t) solve the problems? That’s the approach we’re planning to take.

  30. Yar, I understand that the LC hack isn’t the best thing to use, but until Adobe sort out the problem it looks as though it is our only choice at the moment. I think the code posted in the Ultrashock thread is heading in the right direction, timeline code seems to be unloading correctly now (I double-checked that numerous times), and loading some temp content into the loader also seems to be helping.

    We’ll have to see how things pan out though. If you’re coding your own stuff and know about this issue then it does seem to be avoidable/fixable/hackable, but there are no doubt going to be serious problems with those programmers who aren’t knowledgeable about this kind of stuff.

  31. It would be nice (even if this is fixed in the future without having us to care about it) something along the lines of “UnloadingMainDocumentEvent”, so we could manage in a better way the release of objects or make some sort of checking for saving shared objects or whatever.

  32. Hey Grant —

    Great articles. I have an AS3 project that loads external swf files with timeline code limited to simple stop() and eventlisteners. All swfs have a stop(); action on the first frame, with everything else on succeeding frames. I notice a constant memory usage increase UNTIL the loaded swfs have all played to the end of their timeline and all code has executed. Then memory usage stabilizes. I don’t need or want to unload the assets, but would like to make sure the memory leak doesn’t happen. I guess I need to get my designers to put all their code on frame 1…

    jk

  33. Does any of this apply when loading an AVM1 movie into an AVM2 document?

    For example, i load an AVM1 movie. Am I wrong feel that i can safely avoid a lot of these problems if I just limit the externally loaded swfs (say headers) to being simple AVM1 movies, which i then unload?

  34. Thanks Grant , I came across this post which links to an adobe public bug report/reference system : http://justin.everett-church.com/index.php/2008/04/08/flash-player-needs-your-vote

    I have just clicked through , will have a look if this bug you have mentioned is listed there ..?

    I am pro the “Loader.dispose() or Loader.remove() ” idea ..

  35. Wow, looks like there’s a lot of loading going on in the Flash community.

    I’m working on a game on AIR that loads minigames from “module” swf files, and I’ve been considering the submission process for module developers. Until a system like the one that you describe limits modules’ access to things like the stage, the best option I can think of is to “proofread” each submission’s source code and compile it myself.

    Fortunately, in my case the loaded are in a different security sandbox than my loader, and I can use sandbox bridges to tighten security around my modules. But I doubt that I can protect the stage.

  36. the lastest version of Flash Player 9.0.124.0 was released, but this bug is still there, seems Adobe does not want to fix it.

  37. Dear Grant,

    Thanks for this informative article

    Is this issue carried to AIR as well? Do we have to quit and re-start the air app every time when it becomes slow because of loaded contents (which could not be unloaded)

    Regards,

    Arul

  38. Grant, please log a bug with the Adobe Bugbase ( http://bugs.adobe.com/jira/browse/FP ). I think I speak for many that you are the most authoritative to issue such a detailed bug report, and the sooner it gets logged, the sooner people can vote on it, and the sooner it can be taken seriously. Adobe will pay more attention to its bugbase than a wishlist. Let’s get a bug report petition started!!

  39. YEAH, log a bug.

  40. Hopefully Adobe will fix this problem really soon! I just finished a big project and we tried a thousand solution but none of them worked.

    The best thing to do is keep track of your memory usage from the start of the project. I made a Profiler which is a part of my framework and can be downloaded from http://code.google.com/p/braemar/source/browse/trunk/nl/flashaddict/braemar/utils/Profiler.as

    Hope this helps.

  41. Hi,

    A very thorough and informative article. I am left somewhat saddened that such bug, which must rate as high (if not critical), could persist in the player for so long.

  42. Patrick Polujan April 18, 2008 at 1:04pm

    Has anyone had any success using the new System.gc() method available as of FP9 Update 3?

    Theoretically it’s supposed to force start the garbage collection, but at least in the standalone player, I haven’t noticed any effect.

  43. A presentation about memory management, maybe it’s interesting for others:

    http://labs.realeyes.com/downloads/Memory%20Management%20for%20Flex%20Developers.pdf

  44. Thanks Grant.. It helped me in clearing up certain things that intrigued me in my last job, where i was involved in building UIs for various products..

  45. Hi Grant,

    Thanks a lot of these article as we knew we were sitting on a mine field but didnt really know how to tackle stuff. Some of our problems are now solved, thanks to your articles.

    As soon as the loaded swf is unloaded, we can see this in the debugger output window:

    [UnloadSWF] assets/somefile.swf

    However, for the files which have Flash components, we never see anything like this and I assume it remains in the memory. Do you know any solution to this?

  46. Jarrad Hope May 5, 2008 at 3:00am

    Yes we had this problem in our current project… only for it to rear its ugly head at the end of 2 months … dang

  47. Garbage collection, works great for Java, but Java only has 1 java program and never the case of a java program loading another external java program. Did Adobe forgot that Flash is different from Java in that repsect, with external SWFs running their own code as well? If the SWF is unloaded before actual de-allocation occurs, would GC run for an unloaded SWF’s resources? Definitely not.

    The safest way,it seems, is that all interactivity has to be coded from a cental mainframe or API that is always running to ensure such resources can always be allocated/deallocated safely by GC. Do it in perishable SWFs, well, knowing how GC works, it isn’t surprising…That’s just the way FP9 works.

    Flash galleries can still be done with a LightBox (div layered) js webpage i guess.

    As for enterframe loops, I normallly do a single engine loop from a single mainframe, so i never encountered this issue, since the main engine loop executes the loaded content, and all loaded content are raw and subjected to the parent from a top-down approach. The child “pages” never runs its own code.

    Works for applications and fixed-format websites. But for sites loading 3rd party content or external swfs with their own unique internal code….a NIGHTMARE.

  48. I have the same question as IlTimido which is giving me much trouble so I’ll repost the question:

    Grant, You wrote: if you have any code in your timeline, it will not be possible to unload that SWF.” When you say “timeline code”, do you mean also a simple “stop()” or not? or a simple gotoAndPlay() as a loop on the timeline. Is it impossible to unload these swf’s ?

  49. Matt & IlTimido,

    I haven’t invested a huge amount of time testing this, but it appears to only affect code on running or looping timelines. So once your timeline stops, it should be GCed, but as long as a timeline with code is playing, the SWF will not be collected.

  50. Say, Grant, I think I’ve come up with a terribly inefficient solution to the problem of keeping loaded SWF content from accessing the main application’s Stage instance: BitmapData! Just leave your Loader instance off the display list, but draw it repeatedly to a bitmap object that is!

    This cannot be optimized by computing and using the redraw region to clip the area being drawn. But it is a way of displaying loaded data safely, and could be extended to create mouse events dispatched from the loaded objects themselves.

  51. Thanks for the article Grant. We were thinking of switching our media applications over to AS3 very soon and this has given me food for thought. Will dig deeper now.

  52. These are all expected behaviors … any event listeners are in effect a reference to whatever object they are listening on or listening to. Unload (as an example) would never remove these listener events. A simple solution is to create a manual destructor (remove all listeners and references then unload self or removeChild(this), whatever) … if another object references an object that has had its new ‘destructor’ called, then this object will remain in memory until that object is destroyed too. Soooo, keep track of your references!

    If including no destructors in AS3 is a bug, then I agree, otherwise I would call this an omission of important functionality due to laziness and/or stupidity …

    Keep track of what you create && create destructors && keep code clean == no problems 😉

  53. bennyhands,

    In future, you might want to read the article in its entirety prior to commenting. The items I called out as bugs are in fact recognized bugs in the garbage collector, whereas I specifically mentioned the other items as feature additions.

    Regards.

  54. In the public beta of Flash Player 10, we have done two things to address this issue:

    1. System.gc() is available in all builds and not just the debugger build. This is the preferred way to force a garbage collection instead of the LocalConnection GC hack.

    2. We have changed the garbage collector slightly (when it is explicitly called by System.gc() or the LocalConnection hack) to better clear ENTER_FRAME eventListeners and frame scripts in the timeline. If your child SWF has these types of scripts running, it should not correctly unload…which is different behavior than the FP9 player. A running Timer still creates a hard reference to the child SWF and needs to be explicitly stopped and freed.

    I encourage people to experiment with the Flash 10 beta and see if it helps their unloading issues.

    Werner Sharp

    Flash Player Engineering.

  55. Sorry, I meant to say the child swf should NOW corectly unload with FP10.

  56. Love your blog and experiments, they’re brilliant! I’m just learning Flex/AS3 from AJAX and Java backgrounds. Difficulty freeing objects for collection (exacerbated in this scenario) struck me as immediately disturbing when reading about it in Moock’s book.

    It seems to me (probably naively) a portion of this trouble could be resolved by an abstract Class and accompanying Interface (preferably in the DisplayObject inheritance hierarchy) that monitors listener registration such that when its destroy() method gets called, it iterates over all listeners it has added and removes them from their respective dispatchers.

    In practise, the following code inside of a given Class constructor:

    urlLoader.addEventListener(Event.Complete, completeListener, false, false);

    would be exchanged with the following call to the on() method (the name is inconsequential) inherited from my proposed Class:

    on(urlLoader, Event.Complete, completeListener, false, false);

    Before calling addEventListener() on urlLoader, the on() method implementation transparently logs its arguments to facilitate removeEventListener() by destroy() or even a call to un() with an abbreviated argument list such that:

    un(urlLoader, Event.Complete);

    would remove all Event.Complete listeners added to urlLoader, and:

    un(urlLoader);

    would remove every listener added to urlLoader by the calling Object.

    I intend to apply this technique in my own projects, but if you find it worthwhile maybe you could forward it on?

  57. Ivan Slepchenko June 12, 2008 at 9:40am

    Great article. Thank you very much =)

  58. AWESOME to see Werner’s post that Adobe’s cracked this one. Will definately have to have a go of FP10 and have a play. For those still on FP9 (I know it’s a requirement for my commercial stuff), I’ve written up some processes that have worked for me in the last few weeks, and I thought I’d share and get people’s feedback. You can read the full thing at http://blog.gritfish.net/ (at the moment it’s the first and only post) but I’ll post the juicy stuff here.

    Rather than have a button with the usual frames “normal”, “over”, “hit”, etc. Have your button object contain movieclips for each state, and turn their visibility on or off as you need them. You might have a slightly higher memory usage from having all those extra movie clips (I still need to put in some time to fully test this), but it’ll stay fixed. Same approach works for particle systems. Rather than try and create and destroy your particles, have a set number, and recycle them once they’re done with. That way the only thing actually increasing your memory usage should be loading external assets.

  59. Finally Flash 10 beta 2 has added a feature called “unloadAndStop” which is similar to the unload behavior in ActionScript 2.0: “After calling unloadAndStop on loaded content it will be immediately removed stopping all audio, removing eventListeners, and becoming inaccessible through ActionScript.” http://labs.adobe.com/technologies/flashplayer10/releasenotes.html

  60. Finally Adobe has added a new feature called “unloadAndStop” which is similar to the unload behavior in ActionScript 2.0: “After calling unloadAndStop on loaded content it will be immediately removed stopping all audio, removing eventListeners, and becoming inaccessible through ActionScript” http://labs.adobe.com/technologies/flashplayer10/releasenotes.html

  61. Gee, I thought I was just a bad programmer. I am not insane!

  62. Anthony Mckale July 18, 2008 at 3:46am

    I recently just finished a all flash web project, and i hit these unloading problems hard, thanks to your info about garage collection and memory management I managed to understand what was going on and minimise the background cpu/memory footprint alot,

    it’s good to know these issues are actually a part of flash not just me and my buggy code

  63. got the same prob… 🙁

  64. I have the latest Flash Player installed (9.0.124) and I don’t seem to get the bug you describe. I have an external swf with timeline code on the first frame and the SWF is indeed garbage collected after a certain amount of memory usage has built up. I also attached an ENTER_FRAME listener to the external SWF and it’s still GC’d.

  65. Hey Great thread, there’s an unmentioned issue here that really threw me for a loop. While testing in flash I found it was impossible to remove a swf from memory, I even loaded an empty swf and it still leaked. How ever when I test this same app in IE or FireFox the issue goes away. Apparently this issue is fixed in the new versions of the player but not for the player that CS3 uses. Or perhaps I don’t have the latest cs3 updates or something.

    Anyway, I hope this saves somebody some frustration

  66. 4. Load content into a div layered over your main application. This isn’t a great option, but it addresses almost all of the issues.

    This causes memory leak too. The flash player never clears even if you set innerHtml to “” or style.display to “none”. I doesn’t clear. The memory usage stays at the same levels.

    Is there any possible way to make this work and clear this instance of the player?

  67. Can someone explain what this means, how to do it, and how it addresses the problem?

    You can load content SWFs from a subdomain. This will place it into a security sandbox implicitly.

    thanks

  68. I read this and was well educated by it. But, I think there is a slight oversight… this is the use of the externalinterface and making javascript calls in realtime with flash. Which would easily allow you to embed your ads in HTML but control them using some Javascript animation scripts, etc. This would help prevent the worry about needing a sandbox… for ads anyway.

    Are the TIMER and ENTER_FRAME listeners really bugs? It seems to me that Adobe is really trying to get everyone to move away from timeline scripting and start using OOP principles for coding movies. Let’s face it, a well developed site that relies on OOP AS to power its features and its animation is ( for the most part ) lighter, much more flexible, and more powerful than a site that uses timeline animation and coding….

    My comment comes a bit late, especially with CS4 on the verge of full release, but I figured I’d throw my thoughts out there.

  69. Thanks for the info! As someone who came to Flash from a design instead of a programming background, I’d be interested to know how to educate myself better on memory management issues in AS3. None of my reference books have much to say about the topic. For example, how does one test memory leakage? By running Activity Monitor or Task Manager while your project’s in the browser?

  70. Hey, thanks for article and great comments.

    I look forward to looking at:

    Update: Adobe has added the Loader.unloadAndStop method to Flash player 10 to address some of the issues outlined

    Checkout the comments on

    http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000216.html

    In particular the cast method that allows you to access loaded .swf content.

    Problem arose for me with loaders on consecutive frames loading textfields, should have been simple

    to have coded a backBtn for returning to previous frames, only to find more instances of my textfields being set up top of previous ones, in spite of loader.unload(), removeEventListener and other efforts.

    cheers

    Colm

  71. Great article Grant!!! I have been experiencing issues with AS 3 not being able to unload a swf file with Timer event going on…

    My set up is this: There is a master .fla file that loads multiple swf files consecutively with loader class. In this master .fla file, there is a next button that unloads the current swf file playing and loads the next swf file so the viewer can choose to fastforward to the next movie.

    On one of the swf files (Scene3.swf) there is a Timer event going through the length of the movie. (It is a animation of a bubble floating in the background every 100 milliseconds or so). Within the movie the Timer is stopped and eventListener removed at the end of the movie. Everything is ok until I click on the next button while this movie is playing…I get an error saying:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.

    at Scene3_fla::stage3_1/bubbleTween()

    at flash.utils::Timer/_timerDispatch()

    at flash.utils::Timer/tick()

    I presume it’s because the processor is still processing the movie. Well, the next button unloads each move when it’s clicked, and the child is removed also. I want to tell the next button (which is in the master .fla file) to remove the Timer event with removeEventLister in the externally loaded swf file (Scene3.swf).

    Is there any way to band-aid this issue?

  72. Yikes 🙁 Wish I had discovered this one a long time ago.

    Been experimenting with it myself, and while the Timer thing is absolutely true, I have been able to successfully GC unloaded clips that contained frame code and active ENTER_FRAME listeners.. BUT, much more seriously, it looks like it’s impossible to unload any SWF that has created a Responder object (for an AMFPHP NetConnection, for instance).. This is the most serious problem I’ve found yet, because even if you were to make a standard ‘halt’ function, I haven’t yet found any way to ‘shut down’ a Responder so that the swf can be unloaded (unlike Timers, which can be stopped and nulled to allow the swf that made them to be unloaded.) Just thought I should mention this.

  73. I should probably clarify, it’s only once the Responder has been used in a NetConnection.call() call. (But, note that whether the NetConnection is inside or outside the SWF you’re attempting to unload, using NetConnection.call() will only prevent the unloading if the RESPONDER you used is within the SWF you’re trying to unload.)

  74. hey great article! This really helped me out with a game I’m programming. Each level and animation between are separate SWFs, and as complex as a game can get, there were a lot of timers and events that were left “open”, as it were, and I thought they would be disposed of during unload. Thanks Again.

  75. f useless article. there is no solution!

    and, try using flex memory profiler. That doesn’t work for me either.

    who in gods name is responsible for this.

  76. The article is good but if anybody can give examples for solutions ? I tried everything but still nothing can unload swf that contains ENTER_FRAME function in its parent file. Maybe I do something wrong. Please, anyone post some CODE , not just discussion. That would be really useful for all of us who has the same problem and can’t find a solution.

    Thanks.

  77. Is anyone this problems as well with the newest flash plugin(v10)?

  78. Anyone still experiencing this problems with the latest plugin?(version 10)

  79. Seems to me the best thing would be to give

    developers an explicit ‘delete’ option.

    Why have a ‘delete’ command that may or may

    not work? Not very useful.

    Try this:

    a = {val1:1,val2:2,val3:3};

    b = new Array();

    for(i=0;i

  80. for loop got hosed above, read as

    for( i=0 to 20 ) b[i] = a;

  81. Gee, I thought I was just a bad programmer

    I am not insane

  82. Is it possible to force GC in AS2?

  83. Grant you say:

    “The player team is a group of smart, dedicated people…”

    I don’t see how that can be. How could these people do such a bad job on something so fundamental and important as memory mangagement ? It should have been the very first thing they addressed.

    In reference to flash player 10, it seems memory does get freed eventually, but not when you call GC. Just whenever flash determines it is time. That is most of the memory is freed, but there seems to be a constant on going small build up that is never freed.

    It is not just loader issues, its everything. Anything you do explicity or implicity to allocate memory just builds up to a point before it is actually freed. There seems to be only one memory pool. As this pool reaches a certain size, it is cleaned up as it seems. Most oop allocations are small allocations and are short lived. What makes sense is to use a different pool for small allocations. I have seen small allocations make the totalMemory jump by 20k or more. The small allocation pool could have a ‘time to live’ built in and moved to a master pool if this expires. As memory is freed it should be available for immediate reuse especially in the small allocation pool and even if the pool fragments. Note that on intel machines, the actual location of the memory can move at will and your reference to that memory does not change. The mac used to have a problem with that, but that was years ago. The small allocation pool can probably be about 10k to 20k and serve quite nicely. Most likely it will stay clean and compact if done properly.

    Now it not just memory issues that lead me to believe that Grant’s statement is suspect.

    Its many things but here’s a few others:

    1) htmlText is so slow its hard to believe as it is so basic as well. I do have experience with richtext editors and I just can’t justify this absolutely pool implementation. Also, Adobe does not seem to know they should stop the caret from blinking as you are entering text. Showing a non-blinking caret as you are typing gives much better feedback to the user.

    2) They can’t or won’t allow a different selection background color for TextFields. Someone please take 5 minutes and fix this. This may have been addressed with text.engine but gee I just can’t wait to see what problems exist there.

    3) The code base for flash must be a mess. Why else would it take them years to even get one 64 bit linux beta version out ?

    By the way, why do the ‘smart’ people need to be told when there are such severe problems ? If you are a good programmer at Adobe, then take it into to your own hands and get the job done right!

    Also, it would be good if we actually dump the reference list so we can make better decisions.

    Don

  84. Outstanding article- very well done. Took us most of 2008 to come to the same conclusions…

  85. Here is an app that I use to fix flash problems. There is a demonstration panel that will add various graphical elements including swf’s. I also use it to track memory consumption. For this I use task manager rather than totalMemory because it the more accurate measurement of memory being used. You are best off having a high speed connection for the demonstration elements.

    You can use any name to login.

    http://sms.pangolin.com/vflash/Venus.html

    Don

  86. Anyway, what’s the final result? Here is facing the memory issue also even flash player 10 is used already.

  87. I have a problem with flashPlayer 10. I am runing a video-conference site using FMS and a flash application (AS2) loaded in the browser from the main site. This all ran very nicely until recently, a client was not disconnected when he browsed to another page. The stream and sounds continued to be received and broadcast over the next 5 minutes. Loader.unloadAndStop sounds very interesting but I don’t know how to implement it as I don’t have a “browsed to another page”-event.

    Please help

  88. My team works on a Flash game that loads (and hopefully unloads) a new swf for each game area, so this topic has been of particular interest. Just discovered a few interesting things, some of which contradict the original article. And there’s also a potential solution:

    – first, the presence of code in a timeline doesn’t necessarily always prevent a swf from unloading and cleaning up. Sometimes the presence of that code makes the unload take longer

    – if the loadee is built in CS3, “permit debugging” makes it such that a chunk of memory is left over in System.totalMemory when the swf unloads. This chunk accumulates over subsequent loads

    – recursing through the entire loaded swf and stopping all the timelines allows the swf to unload much more easily when gc happens. Here’s some sample code:

    private static function stopAnimation(obj:DisplayObject):void

    {

    //

    // Recursively search for animation frames

    var mc:MovieClip = obj as MovieClip;

    if (mc && mc.totalFrames > 1)

    {

    mc.stop();

    }

    var container:DisplayObjectContainer = obj as DisplayObjectContainer;

    if (container && container.numChildren)

    {

    for (var i:int = 0; i

  89. That code got munged a little due to the less than, but I think the idea’s straightforward.

    I’ve definitely noticed that there’s a size or complexity threshhold involved in gc’ing away a loaded CS-generated swf. Depending on the size of that swf, the number of frames containing actionscript, and some other random things we’ve noticed, the swf may unload with various ease or not at all. I’ve also noticed that even without invoking the brand new Loader.unloadAndStop, Flash 10 does a much better job at gc’ing away a swf.

  90. I had this problem with a flash based kiosk, which needed to run 24/7. I ended up creating a movieclip cache so that once something was dynamically loaded it stayed in memory forever but was never duplicated. It was definitely a hack kind of solution, but I tried everything I could find on the net and never fixed the gc issue.

    I called a batch file from flash which loaded an exe that scanned the process table for my projector and logged the memory usage periodically. It confirmed that there was no longer a leak with the cache. Although my kiosk capped out at about 800mb of RAM and stayed there.

    Implementing a cache is an expensive way to fix this, but at least it can provide consistent results without running the gc.

  91. Sorry here to be a bit off topic, but not too far off… seems this is mostly about stupidity lol

    This is how the ‘smart’ people at Adobe are responsible for breaking millions of websites and zip from them on it… This will lead you to a fix for a rather serious problem with version detection in AC_RunActiveContent.js

    http://forums.adobe.com/thread/417563?tstart=0

    You can also load a fixed AC_RunActiveContent.js from this site: (look thru the comments)

    http://sms.pangolin.com/rtblog/

    Don

  92. I was building some resilience logic in a streaming video playback app, but realized a week later that it’s just not possible to reset an AS3 instantiated FLVPlayback component into “a proper init state”.

    I guess the unloading problem is the reason for having FLVPlayback.activeVideoPlayerIndex and FLVPlayback.visibleVideoPlayerIndex — because the FLVPlayback instance can NEVER BE UNLOADED/REMOVED !!!

    It’s not really fixed in FP10 as of yet.

  93. I have a flex application that loads ( swfloader ) swfs that in turn load videos via flvplayback. Using FP10 and creating a projector, I have not been able to successfully unload the swfs using any of the techniques described above. It is a serious problem because after several swfs are loaded the cpu begins to chug. Does anyone have experience with this, specifically if flvplayback is involved? I will check back if I find a solution.

  94. I ended up using Loader instead of SWFLoader, as I was unable to get unloadAndStop to work properly with SWFLoader. I am not sure if that is a real bug or not.

  95. David Reuveni June 9, 2009 at 3:42pm

    While I am not a developer of software for flashplayer, I have increasingly noticed that some advertisers have been abusing their readers by activating various active applications which cannot be stopped or blocked when already loaded and which end up using all available CPU time to the extent that you cannot even kill the browser! Adobe has a duty to allow browser users to stop and even kill ad applications which abuse them in this fashion. Putting this differently, if they don’t provide this means, the only conclusion is that they profit from this capability that has been placed in the hands of unethical programmers. The ad menue should provide an unbreakable means to at least stop if not kill any flash- or shock-programmed application, and this should be available to the user more than for the programmer.

  96. Thanks for this post grant. While I’ve read this before, I keep coming back to reference your marksweep diagram.

    I’ve decided to add my own techniques: http://wp.me/pCFcS-r

  97. I suggest to use Event.REMOVED_FROM_STAGE

    addEventListener(Event.REMOVED_FROM_STAGE, onStageRemove);

    function onStageRemove(e:Event):void{

    //remove all event listener

    // cancel loading elements XML, Loader , URLLoader

    // cancel tweens TweenLite.killTweensOf ….

    }

  98. Hi, great helpful post. I understand the concept of the garbage collector and references. Images can e unloaded. That also makes sense to me.

    However I can’t get this concept really clear yet for the Sound class. I came quite far, I have a destroy function that removes every listener, timer or any other reference I make. I set my (mp3player) class to null every time I load another sound in it, manually call the garbage collector, which seems to help, but still memory is slowly adding up.

    Another thing which I can’t find too much information about is whether static classes will be garbage collected or not, or when you focus on memory management, will it be better to avoid static classes?

  99. Great post! I read this article around year ago(somehow still end up here when my frustration with this “bug” is transported to google:) but just want put my thoughts about this dirty “secret” I experienced since AS3 was released, and since there was some rumour about fixing it. I worked on number of projects where memory management was big limitation (in most cases “load another flash stuff” applications). And I can say one thing.

    Flash Player memory management capabilities are just one big joke. Even more ridiculous it sounds when you imagine that on top of this is based flex framework and flash platform overall. Flex allows you to create modular applications…yeah that’s great. Can I really use it? Hell NO! I mean yes you can create some 10 years olds like “modular application” but for anything else it’s just nearly-to-completely impossible. Yes, there is finally unloadAndStop “miracle” but trust me, this just doesn’t help in most cases. Yes we have SWFLoader and “loadForCompatibility” in flex finally but again that useful for app->module scenario maximum. Real multi modular apps are far away from this. Nothing against adobe engineers, I know they do as much as they can (they done remarkable job on mobile) but they should slap their faces for that. Flash Platform would be on completely different level today and many people wouldn’t laugh on it as some sort of advertising toy if this issue wouldn’t be here. I personally had opportunities to create quite complex multi-modular solutions instead of ajax or desktop ones. But it was just too much for little flash player. in every moment like this your faith in player future is questioned. As you said already, there is so much potential on that field since as3 was released. And still nothing. Adobe shouldn’t try to fix this. They should rebuild it. Flash player should be build with modularity (including proper memory management model) from ground zero. Honestly, this along with another even bigger joke called “flash speed” is most annoying thing about flash player since I know it.

  100. I agree with the last comment. Adobe Team should REBUILD from zero the language and the player.

    A new memory management model it’s really essential.

    And they could make a real 3D engine not that joke 2.5D.

    Flash is killing itself, people doesn’t like to wait and even less to see how their system crashes when they open a website.

    That’s why the big companies doesn’t choose Flash for their big projects…

    I love Flash and it’s really annoying and frustrating to renounce and delete my projects…

  101. maquita martinez December 9, 2011 at 8:33pm

    thanks for this…….

Comments are closed.