I'm trying to find memory leaks in a fairly large Flex application and I'm tired of using the paltry tools Flash Builder makes available.
Specifically, I want to analyse the relationships of objects in memory, using the same information Flash Builder's tools appear to have access to. I.e. which objects are in memory, and which objects they have references to, and have references to them. Given that information, I want to construct a directed graph whose nodes are live objects and whose edges are references from one object to another. From there I want to search for dominators, which should be a good indication of which objects are leaking.
I believe Eclipse does something similar for Java.
Unfortunately, Flash Builder only allows the export of its captured profiling data in a binary form that's only parsable by Flash Builder. Rather than try to reverse engineer their output I decided to try to capture the data myself, since they make their profiling API available in the flash.sampler.* package.
So far I've managed to collect the objects that are currently live in memory, get their allocation traces, and references to the objects that I can inspect, which is most of what I need. But I can't figure out how the FB profiler traces back-references to the GC root. The only way I can see to do it is to inspect every object in memory, and for each object inspect each of its properties, and so on, until I find a chain to an object classified as "root" level. But since I can only follow references on publicly visible properties, it's entirely possible I'll miss lots of references that prevent garbage collection.
How does the Flash Builder profiler do it?
My suspicion is that it doesn't just use the sampler.* API to capture information, but supplements that with queries performed through a debugger connection, which is probably out of scope for my work. But in the absence of any way to verify that, I'm hoping it's possible using only the sampler API.
Actually in IMHO if Flash (Flex) Builder's memory / performance tooling is paltry then you aren't using it right. The key to understanding the tooling you have available - has been available since the 4.0 SDK and and I've been using it for every project I've been assigned to as the 'runtime-analysis-guy'.
Live View:
We all know about this one, it gives you a "live" view of what's currently available. While the current instance count is useful, what's even more useful is the cumulative. This helps track down the errant methods which create way too many objects.
Loitering Object View:
You probably aren't using this one, but trust me once you do, you won't go back. With this it helps to have clearly defined small screen / application states (eg. 1. A starting point, 2. The ability to create a dialog 3. A closing point which is the same state as 1). In your application, get to the place you want to test. Then click the memory snapshot function - the "colored lines icon." Now in your application, run through steps 2 and 3. Go back to the profiler, and click this again. Here you can now either terminate or pause your application. Select both memory profiles and click the loitering object function - "the green icon." In theory this list will be empty, but it won't. This shows you what objects have been marked for [sweep] but not [reap]'ed.
D-Click any object and this gives you a detail view with a list of every reference that still holds onto this object. I'll give you a hint right now, if you haven't created a deconstruction process in your application (eg IDestroyable interface), stop right now and go back and do this. You must assign null to every object that is not a complex primative. This means every class, every array, vector, eventlistener and so on.
The sampler package is the only thing the tool uses as far as I'm aware - after all the tool doesn't inject any code into your application at the time of invocation. It's a comparison of all objects with the NewObjectSample and the DeletedObjectSample, and looking at the getSavedThis() going back up the prototype chain (this should return an object where you can call the getSavedThis() on it and so on).
http://help.adobe.com/en_US/flashbuilder/using/WS6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7edf.html
Hope this helps.