Paul:

The links worked much better.

Couple of things:  I'm guessing you are overriding addEventListener somewhere 
and adding the children to a dictionary.  Unless you monkey-patched 
UIComponent, you might have missed an addEventListener call that could be 
important, but on the other hand, addEventListeners on display object rarely 
cause memory leaks.  It is the addEventListener to a Timer or the stage that 
cause the leaks.  The object being "listened to" grabs a reference to the 
object receiving the event.  So it isn't clear you are monitoring the right 
thing.

Also, any attempt to walk EVERY child of a Flex display object has to take into 
account the "chrome".  Look at something like FocusManager to see a tree walk.  
You have to use "rawChildren" in some cases to get every child.

The Dictionary is not weak-reference so anything added to the dictionary is 
stuck if it isn't later cleared and the tree walk seems to only want to clear 
things with "id" properties.  Because the tree itself is disassembled via 
removeChild/removeElement then if one display object is stuck, then all of the 
tree is stuck.

IMO, you don't really need to go through all of this work.  I would first try 
to disassemble the tree where it is easy to do so.  In general it is hard 
because a parent often has property references to the child, but the more you 
disassemble the tree (by calling removeChild/removeElement and setting property 
references to null) then it can be easier to see in the profiler what is still 
being referenced by a "GC root".

HTH,
-Alex

On 2/1/19, 10:39 AM, "Paul Stearns" <[email protected]> wrote:

    Alex:
    
    I will try two things
    
    Here is a link to the clearModuleEvents and related code;
    
    
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fhastebin.com%2Fgiqohitado.js&amp;data=02%7C01%7Caharui%40adobe.com%7Cc6b81fa1950b49b2e47808d6887491cd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636846431574848391&amp;sdata=4yJTgC%2BrfDYl%2BeDVHgZKMGiHsAv1aO4V3Kf5jXy0gdk%3D&amp;reserved=0
    
    Here is a link to the clearEvents and related code;
    
    
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fhastebin.com%2Farilidifol.cs&amp;data=02%7C01%7Caharui%40adobe.com%7Cc6b81fa1950b49b2e47808d6887491cd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636846431574848391&amp;sdata=mndTTfrpeN1gXD0Y69BYuhgs84kapXy0M8JEM8gevgU%3D&amp;reserved=0
    
    Here is the clearModuleEvents code pasted differently;
    
    public function clearModuleEvents(mdlModule:UIComponent):void
    {   trace('Starting clearModuleEvents')   for(var idx:int = 
mdlModule.numChildren - 1; idx >= 0; idx--)   {       trace('idx=' + idx + ' 
isContainer(objChild)=' +isContainer(objChild) + ' 
isContainer(mdlModule.getChildAt(idx))=' + 
isContainer(mdlModule.getChildAt(idx)));       var objChild:DisplayObject = 
mdlModule.getChildAt(idx);       
trace('flash.utils.getQualifiedClassName(objChild)=' + 
flash.utils.getQualifiedClassName(objChild));       var 
childContainer:DisplayObjectContainer = objChild as DisplayObjectContainer;     
  clearChildEvents(childContainer);       childContainer = null;       if 
("clearEvents" in objChild)       {           var fncClearEvents:Function = 
objChild["clearEvents"];           if (objChild.hasOwnProperty('id')) 
trace('Clearing Events in==>>' + objChild['id']);           fncClearEvents();   
        fncClearEvents = null;       }       if ("dataProvider" in 
objChild)objChild["dataProvider"] = null;       if ("selectedIndex" in 
objChild)objChild["selectedIndex"] = -1;       if ("selectedItem" in 
objChild)objChild["selectedItem"] = null;       if ("value" in 
objChild)objChild["value"] = null;       if ("text" in 
objChild)objChild["text"] = null;       objChild = null;   }   objChild = null; 
  trace('Finished clearModuleEvents')
    }
    
    private function clearChildEvents(dpsContainer:DisplayObjectContainer):void
    {   for(var idx:int = dpsContainer.numChildren - 1; idx >= 0; idx--)   {    
   var objChild:DisplayObject = dpsContainer.getChildAt(idx);       if 
(isContainer(objChild))       {           var 
childContainer:DisplayObjectContainer = objChild as DisplayObjectContainer;     
      clearChildEvents(childContainer);           childContainer = null;       
}       if ("killMe" in objChild)       {           var fncKillMe:Function = 
objChild["killMe"];           if (objChild.hasOwnProperty('id')) trace('Killing 
Events in==>>' + objChild['id']);           fncKillMe();           fncKillMe = 
null;       }       else if ("clearEvents" in objChild)       {           var 
fncClearEvents:Function = objChild["clearEvents"];           if 
(objChild.hasOwnProperty('id')) trace('Clearing Events in==>>' + 
objChild['id']);           fncClearEvents();           fncClearEvents = null;   
    }       if ("dataProvider" in objChild)objChild["dataProvider"] = null;     
  if ("selectedIndex" in objChild)objChild["selectedIndex"] = -1;       if 
("selectedItem" in objChild)objChild["selectedItem"] = null;
    //        if ("value" in objChild)objChild["value"] = null;       if 
("text" in objChild)objChild["text"] = null;       objChild = null;   }   
objChild = null;
    }
    
    ----------------------------------------
    From: Alex Harui <[email protected]>
    Sent: 2/1/19 1:20 PM
    To: "[email protected]" <[email protected]>, "[email protected]" 
<[email protected]>
    Subject: Re: instances of objects magically appear...
    It was hard to read the code in the email. In the future, try using 
pastebin or some other service, or open a JIRA issue and put the code in there.
    
    I think I saw that a Dictionary was holding the children but it isn't a 
weak-reference dictionary, so that could pin those children in memory.
    
    HTH,
    -Alex
    
    On 2/1/19, 10:16 AM, "Paul Stearns" wrote:
    
    I am trying to solve my memory leak issue. I have added a clearEvents 
function to my testing modules. My thought is to execute this function prior to 
unloading each module. Towards that end I have created a function in the 
parentApplication called clearModuleEvents which recursively loops through each 
child, and if the "clearEvents " function exists, run it. Then I unload the 
module.
    
    Using the profiler when I execute clearModuleEvents, it seems to create 
another instance of each display object. I am not sure why. I would appreciate 
if someone might tell what might cause that.
    
    Here is the code referenced above;
    
    clearEvents & related code;
    protected var dctListeners:Dictionary = new Dictionary(); override public 
function addEventListener(type:String, listener:Function, useCapture:Boolean = 
false, priority:int = 0, useWeakReference:Boolean = true):void { var key:Object 
= {type: type, useCapture: useCapture}; if (dctListeners[key]) { 
removeEventListener(type, dctListeners[key], useCapture); dctListeners[key] = 
null; } dctListeners[key] = listener; super.addEventListener(type, listener, 
useCapture, priority, useWeakReference); } public function clearEvents():void { 
trace('TestMemoryLeak clearEvents'); try { for (var key:Object in dctListeners) 
{ removeEventListener(key.type, dctListeners[key], key.useCapture); 
dctListeners[key] = null; } } catch (e:Error) { trace('TestMemoryLeak 
clearEvents error='+e.message); } dctListeners = null; }
    
    clearModuleEvents and related code
    
    public function clearModuleEvents(mdlModule:UIComponent):void
    { trace('Starting clearModuleEvents') for(var idx:int = 
mdlModule.numChildren - 1; idx >= 0; idx--) { trace('idx=' + idx + ' 
isContainer(objChild)=' +isContainer(objChild) + ' 
isContainer(mdlModule.getChildAt(idx))=' + 
isContainer(mdlModule.getChildAt(idx))); var objChild:DisplayObject = 
mdlModule.getChildAt(idx); trace('flash.utils.getQualifiedClassName(objChild)=' 
+ flash.utils.getQualifiedClassName(objChild)); var 
childContainer:DisplayObjectContainer = objChild as DisplayObjectContainer; 
clearChildEvents(childContainer); childContainer = null; if ("clearEvents" in 
objChild) { var fncClearEvents:Function = objChild["clearEvents"]; if 
(objChild.hasOwnProperty('id')) trace('Clearing Events in==>>' + 
objChild['id']); fncClearEvents(); fncClearEvents = null; } if ("dataProvider" 
in objChild)objChild["dataProvider"] = null; if ("selectedIndex" in 
objChild)objChild["selectedIndex"] = -1; if ("selectedItem" in 
objChild)objChild["selectedItem"] = null; if ("value" in 
objChild)objChild["value"] = null; if ("text" in objChild)objChild["text"] = 
null; objChild = null; } objChild = null; trace('Finished clearModuleEvents')
    }
    
    private function clearChildEvents(dpsContainer:DisplayObjectContainer):void
    { for(var idx:int = dpsContainer.numChildren - 1; idx >= 0; idx--) { var 
objChild:DisplayObject = dpsContainer.getChildAt(idx); if 
(isContainer(objChild)) { var childContainer:DisplayObjectContainer = objChild 
as DisplayObjectContainer; clearChildEvents(childContainer); childContainer = 
null; } if ("killMe" in objChild) { var fncKillMe:Function = 
objChild["killMe"]; if (objChild.hasOwnProperty('id')) trace('Killing Events 
in==>>' + objChild['id']); fncKillMe(); fncKillMe = null; } else if 
("clearEvents" in objChild) { var fncClearEvents:Function = 
objChild["clearEvents"]; if (objChild.hasOwnProperty('id')) trace('Clearing 
Events in==>>' + objChild['id']); fncClearEvents(); fncClearEvents = null; } if 
("dataProvider" in objChild)objChild["dataProvider"] = null; if 
("selectedIndex" in objChild)objChild["selectedIndex"] = -1; if ("selectedItem" 
in objChild)objChild["selectedItem"] = null;
    // if ("value" in objChild)objChild["value"] = null; if ("text" in 
objChild)objChild["text"] = null; objChild = null; } objChild = null;
    }
    
    
    

Reply via email to