Garbage collection question (display list + action

2019-08-27 02:42发布

问题:

If I add an object that extends a MovieClip or a Sprite to the stage, and I remove that object from the stage, do I need a destroy method if:

  1. There aren't any event listeners attached to that object
  2. I added display objects to that object? (obj.addChild(whatever) --> do I need to remove "whatever" when I remove object from the display list or is that redundant?)
  3. Any instance variables associated with that object - do I need to null those?

回答1:

If you remove all references to a parent object, it is NOT necessary to remove its children DisplayObjects, or null out its member variables, assuming there are no outside references to these children objects.

Flash uses a "mark-sweep" garbage collector. To determine which objects are eligible for garbage collection, Flash starts from the topmost Stage element and traverses any references that it finds, marking objects as it goes. Any objects that were unmarked are unreachable and will be eligible for garbage collection.

Imagine a black box object. If you remove all references to this box, it will be eligible for garbage collection. Now imagine that this black box actually had many subobjects inside of it. Even though there may be references among the parent black box and the child objects, it doesn't change the fact that the black box itself is inaccessible, so all these "inner" references don't matter. These objects will be eligible for garbage collection. You've snipped the branch from the tree, even though the branch itself may have many offshoots and smaller forks.

Here's a simple example:

var obj:MySprite = new MySprite();
obj.foo = new Foo();
obj.addChild(new Sprite());
addChild(obj);

How do we clean up obj and its subcomponents? All that's necessary is:

removeChild(obj);
obj = null;

Now obj is unreachable, and so are its child components. They are all eligible for garbage collection.

You should be careful if you have any external references to these child objects, though:

var obj2:Sprite = new Sprite();
obj.addChild(obj2);
obj = null;

Even though we nulled out obj, we forgot to null out obj2, so it will not be garbage collected. The parent obj object will not be garbage collected, either, because obj2.parent refers to it. If obj is our black box, then our reference to obj2 is pointing inside of the black box!

Therefore, it can be good practice to null and remove things when cleaning up an object, particularly in confusing situations where it's unclear. You'll always be safe if you remove them, but you might end up writing unnecessary code.

If you want to peek at what is going on, it can be helpful to use the profiler tools in Flash Builder, FlashDevelop, or FDT to take a look at the memory usage. You can use the System.gc() call to force the GC to run in debug mode if you want to test these ideas out.