Story of a Pitched Battle With a Massive IE/Flash Memory Leak

This is a short(ish) story of an epic battle between a team of web application developers and IE 7. We were developing a pretty large IE-only application that used a few Flex-based components to provide data visualization capabilities. We were making good progress until well into the testing cycle, when one of the testers came back with a report of IE crashing on a regular basis while using the Flex components. Uh-oh.

I took a closer look at the issue and initially was not able to replicate the issue. The tester sent me some screenshots showing more details of the crash, including a screenshot showing memory usage. System memory was high, but not outrageous. Still, I suspected a memory leak.

A quick bit of background as to how this application works. There are a number of screens which open up an overlay containing our Flex charting application. Those overlays basically consist of a DIV element set up so that it can display some custom content, and also block any clicks to the surrounding page (a modal layer using Yahoo’s UI library). Every time this modal window is opened, it writes a bunch of markup and script into the DIV to set up the Flex app, every time it is closed, it clears out the DIV contents and destroys the app.

Eventually I stumbled on the fact that if I opened and closed this panel 10-15 times (even between visiting other pages), IE would crash. Now at least I had a simple test case to do testing. I did quite a few tests to see if perhaps the Flex application itself was leaking, but the Flash player’s garbage collection seemed to work fine. I used Microsoft’s DebugDiag tool and a tool called sIEve to take a look at what was going on. With sIEve, I saw that there were a whole schwackload of variable handles pointing to each Flex application (22-24, depending on the situation). I would have expected only one or two. I also saw by just monitoring the Windows task manager that each time I opened/closed the modal panel, IE’s memory profile would increase by anywhere from 30-50MB.

I tried many techniques to try to clear these handles (use removeElement on parent and/or child, set handles to null, transfer element to another DIV and delete, set expandoProperty to null), but none worked. I also tried to see what scenarios resulted in a proper cleanup. When I used a popup window, no memory leak occurred. When I used an iframe, no memory leak occurred. Only when I put the Flash application in a DIV element would the leak occur.

Next, I tried to see if it was something about the Flex code that was triggering the leak. I trimmed everything down to a bare bones app, and lo and behold it stopped leaking. I added features back in until it started leaking again, and found that what triggered the problem was Flex’s ExternalInterface library. This library allows a Flex application to call JavaScript methods, and allows JavaScript methods to call Flex methods. In order to make a Flex method available to JavaScript, ExternalInterface injects some JavaScript code into the calling page. This injected code then hangs around, and when the application gets destroyed, IE does not dispose of the additional code. This resulted in orphaned handles that prevented the Flex application from being garbage collected. It so happened that the number of ExternalInterface methods we were exposing corresponded exactly to the number of orphaned handles that sIEve reported for the Flex application, which was my clue that the extra orphaned handles sIEve was reporting were a direct result of the injected ExternalInterface methods.

We were in the process of changing our implementation to use popup windows instead of modal windows (shudder) but at the last minute I got a clue as to how to clear the handles – iterate through the Flash object’s properties and set all the JavaScript methods to null. Something like:

for (var prop in flashHnd)
{
if (typeof(flashHnd[prop]) === "function")
{
flashHnd[prop] = null;
}
}

You can better see how to implement it by taking a look at the source to the SWFUpload project. Take a look at the cleanUp method.

So in the end we were able to deal with this issue in about 15 lines of JavaScript code instead of the significant re-implementation we were otherwise going to have to do right at the end of testing, along with the associated changes in requirements documentation and testing plans. The whole thing reinforced to me though just how much I dislike developing for IE. My guess is that after this experience, the IE-only requirement of this project will likely be reviewed.

4 thoughts on “Story of a Pitched Battle With a Massive IE/Flash Memory Leak

  1. Pingback: Twitter Trackbacks for Mumblings of a Web Developer ยป Story of a Pitched Battle With a Massive IE/Flash Memory Leak [nathanderksen.com] on Topsy.com

  2. Hey there Guillaume, thanks, I actually reported the issue with Microsoft (our customer has a support contract with them) and also brought it up with Adobe support (we have a partnership agreement with them). Microsoft closed the issue once I found this fix as the issue does not happen with IE 8. I’m not sure if Adobe can do much to fix the issue, unfortunately, but I’ll try submitting a bug report with them as well at the link you gave.

Comments are closed.