令人困惑的垃圾收集问题

时间:2010-09-25 09:49:17

标签: actionscript-3

1) var x1:X = new X();
2) var x2:X = new X();
...
3) x1.z = new SWFLoader(...);
...
4) x2.z = x1.z;
5) x1.z = null
6) x1 = null;

最后一个语句没用,因为语句4保证只要x2.z存在,x1及其包含的任何其他内容永远不会被垃圾回收。有没有人认为这是奇怪的?对于我需要做的事情,这对我来说是一个重大的冲击和缺点。有任何解决方法吗?

这个有意义的唯一原因是x1中的所有内容都存储在连续的内存或其他内容中,但是当你在大多数语言中说“x1.z = new ...”时,这意味着它会进入并分配一个新的块在其他地方的内存并返回一个指向它的指针(随后也指向x2.z的指针。)我总是将actionscript中的“reference”解释为“指针”。

当然有些人可能会说,你仍然可以单独删除x1中的所有内容。但如果不是上面的声明4,声明6会将x1中的所有内容标记为删除。

(注意:我将声明5放入的唯一原因是告诉flash播放器“我真的不在乎x1.z了”,但它没有任何区别。)

2 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,那么您说以下代码应该泄漏x1。但事实并非如此。您如何测试x1不符合收集条件?你能发布一些可以重现问题的工作代码吗?

package {
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.net.URLLoader;
    import flash.system.System;
    import flash.utils.Dictionary;
    import flash.utils.setInterval;

    public class test extends Sprite
    {

        private var _dict:Dictionary = new Dictionary(true);

        private var x1:Foo;
        private var x2:Foo;

        public function test()
        {
            testGC();
            setInterval(function():void { 
                traceCount();
            },100);         
        }

        private function testGC():void {
            x1 = new Foo();
            x2 = new Foo();

            _dict[x1] = true;
            _dict[x2] = true;

            x1.z = new URLLoader();
            x2.z = x1.z;

            x1 = null;


        }

        private function traceCount():void {
            var count:int = 0;
            for each(var i:* in _dict) {
                count++;
            }
            trace(count);
            System.gc();
        }

    }
}

import flash.net.URLLoader;

class Foo {

    public var z:URLLoader;
}

答案 1 :(得分:0)

我只是试图用新代码复制它而无法复制,所以我不知所措。原始代码现在被还原,并且该类比我刚刚提出的测试场景大得多。我猜我最好关闭它。这是我刚刚运行的测试场景,FWIW:

package my_components 
{

  import mx.controls.SWFLoader;

  public class Test {

    public var arr:Array = new Array();

    public var z:SWFLoader;

    public function Test() {
      for (var n:int=0; n<1000000; n++)
        arr.push(n);
    }  

  }

}       

private var x1:Test;
private var x2:Test;

private function InitWR(fnCFG:String = null):void {

  try { 
    new LocalConnection().connect('foo'); 
    new LocalConnection().connect('foo'); 
  } catch (e:*) {} 

  Dumper.info(System.totalMemory.toString());   

  x1 = new Test();
  x1.z = new SWFLoader();

  x2 = new Test();

  x2.z = x1.z;

  x1 = null;

  try { 
    new LocalConnection().connect('foo'); 
    new LocalConnection().connect('foo'); 
  } catch (e:*) {} 

  Dumper.info(System.totalMemory.toString());   

  Dumper.info("---------------");