2 Replies Latest reply on Jul 23, 2010 7:08 PM by Aaronius9er9er

    Profiler - Incorrect GC root, lack of info

    Aaronius9er9er Level 1

      So I've been doing some research on how the profiler behaves under various memory leak scenarios and this one, though simple, baffles me.

       

      Here's my main app code:

       

       

      <?xml version="1.0" encoding="utf-8"?>
      <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:s="library://ns.adobe.com/flex/spark" 
                        xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
           <s:layout>
                <s:VerticalLayout/>
           </s:layout>
           <fx:Script>
                <![CDATA[
                     import mx.collections.ArrayCollection;
                     
                     [Bindable]
                     public var users:ArrayCollection = new ArrayCollection();
                     
                     protected var myComp:MyComponent;
                     
                     protected function removeButton_clickHandler(event:MouseEvent):void
                     {
                          myComp = null;
                     }
      
                     protected function addButton_clickHandler(event:MouseEvent):void
                     {
                          myComp = new MyComponent();
                          myComp.dataProvider = users;
                     }
                ]]>
           </fx:Script>
      
           <fx:Declarations>
                <!-- Place non-visual elements (e.g., services, value objects) here -->
           </fx:Declarations>
           <s:Button label="Remove" click="removeButton_clickHandler(event)"/>
           <s:Button label="Add" click="addButton_clickHandler(event)"/>
      </s:Application>
      

       

       

      Notice that MyComponent doesn't actually get added to the stage.  I'm just creating it and setting the dataProvider property.  Now here's MyComponent:

       

       

      package
      {
           import mx.collections.ArrayCollection;
           import mx.core.UIComponent;
           import mx.events.CollectionEvent;
           
           public class MyComponent extends UIComponent
           {
                public function MyComponent()
                {
                     super();
                }
                
                private var _dataProvider:ArrayCollection;
                
                public function get dataProvider():ArrayCollection
                {
                     return _dataProvider;
                }
                
                public function set dataProvider(value:ArrayCollection):void
                {
                     _dataProvider = value;
                     
                     _dataProvider.addEventListener(
                               CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
                }
      
                private function collectionChangeHandler(event:CollectionEvent):void
                {
                     
                }
           }
      }
      

       

       

      Nothing special.  It adds an event listener to the ArrayCollection coming in.  It's a strong reference, so it causes a memory leak because it's never removed.

       

      Now here's what the Object References view in the profiler shows for MyComponent:

       

      http://screencast.com/t/YjVlYWQ5Z

       

      Now how in the world is MyComponent the GC Root?  And why does it make no mention that the ArrayCollection has a reference to MyComponent's event listener function.  All I learn by looking at the profiler is that MyComponent isn't getting garbage collected but nothing about why.

       

      Please enlighten me.  Thanks.