Flex内存优化专题之——1、垃圾回收机制
Flash Player 垃圾回收工作是由垃圾回收器(garbage collector)完成的。垃圾回收器是
运行在后台的一个进程,它释放那些不再被应用所使用对象所占用的内存。不再被应用所
使用的对象是指那些不再会被那些活动着(工作着)的对象所“引用”的对象。在 AS 中,
对于非基本类型(Boolean, String, Number, uint, int)的对象,在对象之间传递的都是对象引用,
而不是对象本身。删除一个变量只是删除了对象的引用,而不是删除对象本身。一个对象
可以被多处引用,通过这些不同的引用所操作的都是同一个对象。
通过以下两段代码可以了解基本类型和非基本类型对象的差异:
基本类型的值传递:
private function testPrimitiveTypes():void { var s1:String="abcd"; // 创建了一个新字符串 s1 ,值为 "abcd" var s2:String=s1; //String 是基本类型,所以创建了一个新的字符串 s2 , s2 的值拷贝自 s1 。 s2+="efg"; // 改变 s2 的值 s1 不会受影响。 trace("s1:",s1); // 输出 abcd trace("s2:",s2); // 输出 abcdefg var n1:Number=100; // 创建一个新的 number, 值为 100 。 var n2:Number=n1; //Number 是基本类型 , 所以又创建一个新 number n2,n2 的值拷贝自 n1 。 n2=n2+100; // 改变 n2 对 n1 不会有任何影响。 trace("n1",n1); // 输出 100 trace("n2",n2); // 输出 200 }
非基本类型对象的引用传递:
private function testNonPrimitiveType():void { // 创建一个新对象 , 然后将其引用给变量a : var a:Object = {foo:"bar"} // 将上面所创建对象的引用拷贝给变量b(通过变量b建立对对象的引用) : var b:Object = a; // 删除变量 a 中对对象的引用 : delete(a); // 测试发现对象仍然存在并且被变量 b 所引用: trace(b.foo); // 输出 "bar", 所以对象仍然存在 }
对于非基本类型对象,AS3 采用两种方法来判定一个对象是否还有活动的引用,从而
决定是否可以将其垃圾回收。一种方法是引用计数法,一种方法是标记清除法。
Reference Counting
引用计数法是判定对象是否有活动引用的最简单的一种方法,并且从 AS1 就开始在
Flash 中使用。当创建一个对对象的引用后,对象的引用计数就加一,当删除一个引用时,
对象的引用技术就减一。如果对象的引用计数为0,那么它被标记为可被 GC(垃圾回收器)
删除。例如:
var a:Object = {foo:"bar"} // 现在对象的引用计数为1(a) var b:Object = a; // 现在对象的引用计数为 2(a 和b) delete(a); // 对象的引用计数又回到了 1 (b) delete(b); // 对象的引用计数变成 0,现在,这个对象可以被 GC 释放内存。
引用计数法很简单,并且不会增加 CPU 开销,可惜的是,当出现对象之间循环引用时它就
不起作用了。所谓循环引用就是指对象之间直接或者间接地彼此引用,尽管应用已经不再
使用这些对象,但是它们的引用计数仍然大于0,因此,这些对象就不会被从内存中移除。
请看下面的范例:
//创建第一个对象: var a:Object = {}; // 创建第二个对象来引用第一个对象: var b:Object = {foo:a}; //使第一个对象也引用第二个对象: a.foo = b; // 删除两个活动引用: delete(a); delete(b);
上面的例子中两个活动引用都已被删除,因此在应用程序中再也无法访问这两个对象。但
是它们的引用计数都是1,因为它们彼此相互引用。这种对象间的相互引用可能会更加复
杂(a 引用 b,b 引用 c,c 又引用 a,诸如此类),并且难以在代码中通过删除引用来使得引
用技术为变为0。Flash player 6 和 7 中就因为 XML 对象中的循环引用而痛苦,每个 XML
节点既引用了该节点的子节点,又引用了该节点父节点。因此,这些 XML 对象永远不会释
放内存。好在 player 8 增加了一种新的 GC 技术,叫做标记清除。
标记清除(Mark Sweeping)
AS3 使用的第二种查找不活动对象的 GC 策略就是标记清除。 Player 从应用的根节点
开始(在 AS3 中通常被称为”根(root)”),遍历所有其上的引用,标记每个它所发现的
对象。然后迭代遍历每个被标记的对象,标记它们的子对象。这个过程第归进行,直到
Player 遍历了应用的整个对象树并标记了它所发现的每个东西。在这个过程技术的时候,
可以安全地认为,内存中那些没有被打标记的对象没有任何活动引用,因此可以被安全地
释放内存。可以通过下图可以很直观地了解这种机制(绿色的引用在标记清除过程中被遍
历,绿色对象被打上了标记,白色对象将被释放内存)

标记清除机制非常准确,但是这种方法需要遍历整个对象结构,因此会增大 CPU 占用 率。
因此,Flash Player9 为了减少这种开销只是在需要的时候偶尔执行标记清除活动。
注意:上面所说的引用指的是“强引用(strong reference)”,flash player 在标记清
除过程中会忽略“弱引用(weakness reference )”,也就是说,弱引用在标记清除过程
中不被当做引用,不会阻止垃圾回收。

浙公网安备 33010602011771号