ActionScript3 内存管理 ---Garbage Collector

来源:互联网 发布:优化楼梯间出入口标识 编辑:程序博客网 时间:2024/04/27 11:03

抄文如下:

首先看看AS的回收机制

Flash中的无用单元回收机制(Garbage Collection)用来自动清除内存中不再需要的变量,有两种算法执行:

引用计数 和 标识和清除.
    引用计数用来追踪内存中对象的所有引用,当我们创建一个指向这个对象的引用时,它的引用计数就进行增1操作.
var a:Object = new Object(); // new Object in memory given reference count of 1
var b:Object = a; // Object now has reference count of 2

    当内存中不再存在任何指向这个对象的引用时,无用单元回收器(GC)会将这个对象从内存中清除掉.

delete a; // Object has reference count of 1
delete b; // Object has reference count of 0, removed from memory

    要注意的是,delete 操作符只是用来删除相关的变量,但是,它并不会将对象从内存中清除掉,那是无用单元回收器的工作,还有,delete 操作符不能删除类成员变量.
    引用计数在有些时候并不能正常工作.例如,如果你定义两个对象,它们只是引用自身,而没有任何别的对象引用它们,这样它们的引用计数是大于0的,可以却没有办法访问到它们.

var a:Object = new Object(); // reference(a) count 1
var b:Object = new Object(); // reference(b) count 1
a.b = b; // reference(b) count 2
b.a = a; // reference(a) count 2
delete a; // reference(a) count 1
delete b; // reference(b) count 1

    这里对象a和对象b已经从当前作用域内删除掉(delete)了,所以它们是没有办法访问到的.但是,从对象a仍然是可以访问对象b的,而且对象a也可以从对象b访问到.对象a和对象b看起来已经被程序员手动删除一样,而实际上,它们还存在于内存中,而且它们的引用计数还大于0的,所以这种情况下引用计数有很大的缺陷,而标记-清除算法可以解决.
    标记-清除算法是这样一个过程,程序会在一个基础的区域(比如root或舞台stage)扫描所有的对象和引用,标记出已经发现的,那些没有发现的是不能被访问到,或者已经被删除(delete)掉的.还拿上面对象a和对象b的例子来说,因为对象a和对象b都不能被根目录(root)下任何对象访问到,它们不会被标记,最后会被无用单元回收器(GC)清理掉.

//扫描过程描述
[root] <- scan…
[objectRef (marked)] <- scan…
[objectRef (marked)] <- scan…
[objectRef (marked)] <- scan…

[delete all objects not marked]

    标记-清除算法相对于引用计数可能会花费较多的时间,也不会像后者那样频繁的执行.事实上,有时候它在影片中几乎是不执行的,当标记清除执行时,时间轴已经经过了好多帧了,也就是说,有时候你觉得变量已经从内存中删除掉了,而实际上它还会在内存中存在一段时间.对于那些与对象的脚本,比如enterFrame事件,当对象实际删除之前这些事件还在执行,所以你始终应该记得在不使用的时候清除(clearup)你的事件.

什么是弱引用(Weak Reference)

 


   如果你想使用一个不被GC计数的引用,可以定义一个弱引用.弱引用会被引用计数器忽略掉,即使引用的对象被删除(delete)了,而弱引用还可以存在.
    AS3.0中的弱引用是不能到处使用的,只能在以下两个地方使用:一是用于Dictionary对象,Dictionary类的构造器使用一个可选择的参数来决定Dictionary实例的键值是否使用弱引用.默认情况下为false,使用的是强引用,如果设置为true,使用弱引用.

var dict:Dictionary = new Dictionary(true); // use weak references as keys

    如果你做了上面的操作,那么你用来存放数据的键值不会被算做对象的引用,也就是对象引用计数不会增加.

var obj:Object = new Object();
dict[obj] = true;
delete obj; // obj can be garbage collected since the dict reference isnt counted

    另外可以在EventDispatcher类的addEventListener方法指定弱引用,addEventListener方法有一个参数可以用来指定侦听器引用为弱引用.

// addEventListener(type:String, listener:Function, useCapture:Boolean= false, priority:int = 0, useWeakReference:Boolean = false):void
addEventListener(MouseEvent.CLICK, clickHandler, false, 0 true); // use weak references

    默认情况下这个参数也为false,使用强引用,这里指定侦听器引用为弱引用,从而调用无用单元回收器(GC)来回收无用侦听器,是一个好的习惯.

原创粉丝点击