16 Replies Latest reply on Oct 12, 2011 1:23 PM by Carl A Looper

    Memory increases, GC does not collect.

    Neil Prestemon

      I am developing an AIR application using FlexBuilder (FlashBuilder) 4.0.1 (Standard) in an Eclipse plugin environment, on the Windows 7 64-bit platform.


      My application is intended to run full-screen, on a touchscreen device, as an application for small children (pre-k).

      The general operation is to present a series of scenarios, one by one, from a collection of separately developed swf files. (each swf file is a scenario).  The child responds to the swf file, the swf file sends an event to the player, which performs an unloadAndStop() on the Loader object that loaded the swf.  Then the next swf is loaded.


      The problem we are seeing is that each swf file adds about 15-25 MB to the Workingset Private allocation of the AIR application (or the ADL.EXE runtime).  Very little of this RAM is returned.  After about 140 of these scenarios, the AIR runtime consumes about 1.6 GB of RAM.  This, in itself, is not the problem - we could buy more RAM.


      The problem is that the Loader crashes here, and takes the whole AIR runtime with it.


      We also have a few "special purpose" swf files which are basically just wrappers around a s:VideoPlayer control, that plays a bindable file - .flv video, and the complete event fires the event that tells the AIR player to unloadAndStop the swf.

      Since the video player took no manual intervention to test, I built a set of these to simulate a high load, and found that:

      The .flv files are opened, but they are never closed. Since the s:VideoPlayer control is an MXML construct, there is no explicit way I can see to tell it to close the dang file when it's done.  (it's not documented, anyway).

      At exactly 32 video-swf items, the videos will continue to play, but there is no more audio.

      At exactly 73 video-swf items, (seemingly regardless of the SIZE of the .flv file I select), the 73rd item crashes the Loader (and AIR player).


      I supply unloadAndStop() with the (true) parameter.  I follow it with a System.gc().

      I explicitly remove ALL of my listeners. (in the AIR player application - I assume no control over items within the swf items that I am playing, since we assume we eventually may end up playing 3rd-party developed items; so we rely only on the return of a completion event, and a data structure).

      I explicitly close() ALL of my audio streams. (at the AIR player level - not in the swfs.)

      I explicitly stop() ALL of my timers.

      My loader is instantiated in an element called "myLoaderContainer" - and after I receive my completion event, I do a myLoaderContainer.removeAllElements();


      I have tried both the System.gc() call and the "unsupported"  LocalConnection().connect('foo') call.  both of these have zero effect. (in other words, I think there is probably no garbage to collect).


      Still, I find it strange that nowhere, is it written, any kind of hint about how often garbage collection will do it's thing, and having graphed the flash.system.System.privateMemory; usage against all of my functions, and narrowed it down to my loader, and seeing that this allocation is never reclaimed, even on loader.unloadAndStop(true); - I wonder exactly what is the (true) parameter for, in that method?


      I don't know what else I am supposed to do to force my Loader to *actually* unloadAndStop().

      One would think that unloadAndStop() would not mean: "cease all functioning, but continue to occupy memory until the parent application chokes on it's own heap."

        • 1. Re: Memory increases, GC does not collect.
          Neil Prestemon Level 1

          . . .

          I also changed all of my listener references to "weakly-referenced".  This did not change the behavior of the program (neither with listeners firing, nor with garbage collection).

          • 2. Re: Memory increases, GC does not collect.
            chris.campbell Adobe Employee

            Thank you for the detailed explanation.  Would you mind opening a new bug on this at http://bugbase.adobe.com?  If you could, please post letting me (and others) know the bug URL and I'll follow up internally.





            PS. Do you know if this behavior also occurs with AIR 2.5.1?

            • 3. Re: Memory increases, GC does not collect.
              chris.campbell Adobe Employee

              I forgot to mention, but if possible please provide any sample code or your test application that can demonstrate the problem.  This will make debugging much easier.  If you'd rather keep this off the public bug report, please feel free to send it to me directly at ccampbel@adobe.com.

              • 4. Re: Memory increases, GC does not collect.
                Neil Prestemon Level 1

                Providing source code would be difficult; because there are contractual issues, but we are working on obtaining permission from our customer.


                Same behavior in 2.5.1 and 2.0.2.

                • 5. Re: Memory increases, GC does not collect.
                  Frederico Mota Garcia

                  I'm facing the exact same issue. I'm loading swf's into an AIR app, and when I unload them memory is never cleared. After some time using the application memory also increases to a critical level, crashing AIR.


                  I've made some tests, and what I found was that unloadAndStop() is not working in AIR 2.5, 2.5.1 or 2.6. Also it does not work in Projector or Firefox plugin.


                  The same code works perfectly in IE.


                  This is really a big issue for me. Our application loads swf's that might not have been developed by us, and until this bug is not fixed, we must review all contents provided to us and make sure all references are removed manually.

                  • 6. Re: Memory increases, GC does not collect.
                    Neil Prestemon Level 1

                    I have posted this as:



                    I also provided some pseudo-code in hopes that this is far enough from my source to be "legal" and close enough that it shows how to reproduce the problem.


                    I spread a bunch of:

                    trace("privateMemory after <function_name>: " + flash.system.System.privateMemory);

                    calls all throughout the code, and pasted them into a text file, imported it into Excel, and created a graph, as a crude from of profiling.

                    The worst offender in terms of memory consumption, appears to be after I read my swf file into a ByteArray, then use loadBytes, contruct a UIContainer, and addChild to put the Loader object into that container.  Then; I have an mxml-defined "BorderContainer", and when I addElement(UIContainer) that's when the memory shoots way up.


                    After - I close that file-stream, de-reference the ByteArray, unloadAndStop the swf, and dereference the UIContainer, then removeAllChildren() to my BorderContainer. Then I invoke the System.gc(). A small amount of memory is reclaimed, at that time.

                    • 7. Re: Memory increases, GC does not collect.
                      Neil Prestemon Level 1

                      I was notified that this was a duplicate of a couple of other bugs, but when I search on those bug ID numbers, they do not return in the search.

                      • 8. Re: Memory increases, GC does not collect.
                        chris.campbell Adobe Employee

                        Those are internal numbers,  I'll relate the bugs and as the internal status changes we should see an update in the external bug.  If you don't see any updates, please feel free to ping me and I'll update the thread.


                        It might also be helpful to join our prerelease program.  This way we can verify our changes on your actual code.  If this is something you're interested in please email me (ccampbel@adobe.com) your name, email and company name/website and we'll get the process started.




                        • 9. Re: Memory increases, GC does not collect.
                          Neil Prestemon Level 1

                          This project was sidelined for the summer, due to budget constraints.  However, I have re-tested my code (using regular "scenarios", not the test-harness videos I had set up, back in May).  I tested with the 2.7.1 player, and the (beta) player.


                          The 2.7.1 player crashed after 142 scenarios - (which is fairly consistent with the behavior of 2.0.2 and 2.5.1) - however, the previous player versions would exhibit load-delays, audio stuttering, and overlap (sound-clips would be delayed, and play on-top-of eachother, instead of at the specified time).  These secondary symptoms would only appear when the player was near it's "limit" (within 10-20 of the last scenario) and almost ready to crash.  These other symptoms no longer occur in 2.7.1, and now, the whole application simply crashes (exits) when the "limit" is reached.


                          The (beta) player also seems to have fixed the secondary symptoms of load-delays, audio stuttering, and audio overlap.  But this player plays 162 scenarios before crashing.  So there is an apparent improvement in the gc performance. But there are still resources that are left out at each load/unload cycle.  (I did not test with any instrumentation enabled, so I don't have memory values).

                          • 10. Re: Memory increases, GC does not collect.
                            chris.campbell Adobe Employee

                            Thank you Neil, I'll update our bug with your findings.  Have you had a chance to try out the AIR 3 RC build (

                            • 11. Re: Memory increases, GC does not collect.
                              chris.campbell Adobe Employee

                              Hi Neil,

                              Found the following information in one of the related bug reports:


                              "You must modify your code to change NetStream.close() into the new NetStream.dispose()."


                              Are you currently using NetStream.close()?  If so, would you mind giving the new API a try?


                              http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/NetStrea m.html#dispose%28%29




                              • 12. Re: Memory increases, GC does not collect.
                                Neil Prestemon Level 1


                                I had been using the gc call, not NetStream.


                                I am playing .swf files from the system's local hard drive.


                                I load the swf file as a ByteArray, using FileStream.open and

                                FileStream.readBytes, then Loader.loadBytes.


                                I am not sure how I would use NetStream in this context.



                                • 13. Re: Memory increases, GC does not collect.
                                  Neil Prestemon Level 1

                                  I am loading the swf file from the local file system as a Byte Array, using FileStream.readBytes() and Loader.loadBytes(). 


                                  If I cast the FileStream as a NetStream, can I use the dispose() method?

                                  • 14. Re: Memory increases, GC does not collect.
                                    chris.campbell Adobe Employee

                                    Hi Neil,

                                    We're going to investigate further and someone from the team should be in contact with you (either through the bug, this thread or email).



                                    • 15. Re: Memory increases, GC does not collect.
                                      Carl A Looper

                                      I experienced a similar problem with a small AIR app that was using a socket server to transfer bytearray data (9 floats in an ongoing cycle). I can't recall what version of AIR I was using. I've since installed 3.0 but haven't tried recompiling with that yet. But I will. In any case there was a memory leak that kept expanding the RAM usage until the program eventually crashed. Yet using the same version of AIR,and same socket server code, it was transferring a humungus lot of integers in an ongoing cycle (representing video camera data) without any problem.

                                      • 16. Re: Memory increases, GC does not collect.
                                        Carl A Looper Level 1

                                        I recompiled the memory leaking program using AIR 3.0 and the leak remains. However my previous description of the problem was incorrect. It's not a bytearray I'm using. It's just a normal  array, of 9 floats. Now this array is is being updated in an event, on an indefinite basis (from hardware data provided by a separate process running as a socket server). The updating array  is a class scope array. On each update the index restarts to zero (ie. it's not a ballooning array). However, each item of that updating array is then being redispatched in the context of another socket event (request events by another process), using socket.writeDouble() - also on an indefinite basis.


                                        So while the array is being written in the context of one event, it's simultaneously being read in the context of another uncorrelated event.


                                        My only theory is that the speed at which the array is being written/read (since only nine floats) is causing some overflow in the number of temporary arrays that might be generated to accomodate such abuse. And that maybe such temps are becomining lost to the gc - that pehaps the gc can't keep up with the abuse. But that's just me speculating what theorys I could test for workarounds.


                                        In native code I'd use various thread controls (mutexes etc),  to control read/writes on the async socket events, but here I'm somewhat at a loss as to how to otherwise control the data flow. Indeed I ended up rewriting the program  in native code (c++) to get around the memory leak.