您的位置:首页 > 其它

Flash AS3 垃圾回收机制详解

2012-10-06 15:20 330 查看
英文原文:http://gskinner.com/blog/archives/2006/06/as3_resource_ma.html

http://active.tutsplus.com/tutorials/workflow/quick-tip-understanding-garbage-collection-in-as3/

关于垃圾收集器

垃圾收集器是一个后台进程它负责回收程序中不再使用的对象占用的内存。非活动对象就是不再有任何其他活动对象引用 它。为便于理解这个概念,有一点非常重要,就是要意识到除了非原生类型(Boolean, String, Number, uint, int除外),你总是通过一个句柄访问对象,而非对象本身。当你删除一个变量其实就是删除一个引用,而非对象本身

以下代码很容易说明这一点:

// create a new object, and put a reference to it in a:
var a:Object = {foo:"bar"}
// copy the reference to the object into b:
var b:Object = a;
// delete the reference to the object in a:
delete(a);
// check to see that the object is still referenced by b:
trace(b.foo); // traces "bar", so the object still exists.


如果我改变上述示例代码将b也删除,它会使我创建的对象不再有活动引用并等待对垃圾收集器回收。

用两种方法定位无引用的对象 : 引用计数法(Reference Counting)和标识清除法(Mark Sweeping)。

引 用计数法

引用计数法是一种用于跟踪活动对象的较为简单的方法,它从ActionScript1.0开始使用。当你创建一个指向某个对象的引用,该对象的引用计数器 加1;当你删除该对象的一个引用,该计数器减1。当某对象的计数器变成0,该对象将被标记以便垃圾回收器回收。

var a:Object = {foo:"bar"}
// the object now has a reference count of 1 (a)
var b:Object = a;
// now it has a reference count of 2 (a & b)
delete(a);
// back to 1 (b)
delete(b);
// down to 0, the object can now be deallocated by the GC


引用计数法简单,它不会非CPU带来巨大的负担;多数情况下它工作正常。不幸地是,采用引用计数法的垃圾回收器在遇到循环引用时效率不高。循环引用是指对象 交叉引用(直接、或通过其他对象间接实现)的情况。即使应用程序不再引用该对象,它的引用计数器仍然大于0,因此垃圾收集器永远无法收集它们。下面的代码 演示循环引用是怎么回事:

var a:Object = {}
// create a second object, and reference the first object:
var b:Object = {foo:a};
// make the first object reference the second as well:
a.foo = b;
// delete both active application references:
delete(a);
delete(b);


上述代码中,所有应用程序中活动的引用都被删除。我没有任何办法在程序中再访问这两个对象了,但这两个对象的引用计数器都是1,因为它们相互引 用。循环引用 还可以更加负责 (a 引用 c, c引用b, b引用a, 等等) 并且难于用代码处理。FlashPlayer 6 和 7的XML对象有很多循环引用问题: 每个 XML 节点被它的孩子和父亲引用,因此它们从不被回收。幸运的是FlashPlayer 8 增加了一个叫做标识-清除的新垃圾回收技术。

标 识-清除法

ActionScript3.0 (以及FlashPlayer 8) 垃圾回收器采用第2种策略标识-清除法查找非活动对象。FlashPlayer从你的应用程序根对象开始(ActionScript3.0中简称为 root)直到程序中的每一个引用,都为引用的对象做标记。 接下来,FlashPlayer遍历所有标记过的对象。它将按照该特性递归整个对象树。并将从一个活动对象开始能到达的一切都标记。该过程结束 后,FlashPlayer可以安全的假设:所有内存中没有被标记的对象不再有任何活动引用,因此可以被安全的删除。图1
演示了它如何工作:绿色引用(箭头)曾被FlashPlayer 标记过程中经过,绿色对象被标记过,白色对象将被回收。



转自:http://kevincao.com/2011/08/actionscript-garbage-collection-1/

一次GC过程(GC Pass)分为以下两个步骤:

Reference Counting

统计所有对象的引用计数,如果某个对象没有任何引用,就标记为可回收。



这个操作很好理解,需要强调的是weak reference(弱引用)是不参与计算的。引用计数是一个相对省CPU的操作,能够筛选出大部分可回收资源,但是对一些循环引用的情况就无能为力了。在下图中,标记为绿色的对象每个的引用数都为1,但它们明显是应该被回收的。



所以GC需要进行第二个步骤:

Mark Sweeping

这个步骤是从根对象(Root)开始轮询对象的引用。所谓的根对象包括:

Stage对象

静态变量

局部变量

这种方式足够精确,能够成功筛选出上图中绿色标记的对象,而它的代价就是较大的计算开销。

为了帮助GC过程更高效的执行,最好是能在第一步引用计数中就把需要回收的对象都标记出来。具体的做法就是把所有不需要的对象引用全部清空,包括:

删除成员变量的引用

从可视对象列表上移除对象

移除事件监听

参考资料:
http://gskinner.com/blog/archives/2006/06/as3_resource_ma.html http://www.gskinner.com/talks/resource-management/ http://active.tutsplus.com/tutorials/workflow/quick-tip-understanding-garbage-collection-in-as3/ http://blogs.adobe.com/aharui/2007/03/garbage_collection_and_memory.html
网上相关主题文章:
http://ticore.blogspot.com/2010/11/as3-loader-object-gc-behavior-1.html http://ticore.blogspot.com/2010/11/as3-loader-object-gc-behavior-2.html http://blog.onthewings.net/2010/10/18/how-to-know-objects-are-really-gced-in-flash-as3/ http://www.gskinner.com/blog/archives/2006/07/as3_weakly_refe.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: