zoukankan      html  css  js  c++  java
  • actionscript3垃圾回收机制及内存管理

    actionscript3垃圾回收机制及内存管理

    分类: Actionscript 455人阅读 评论(1) 收藏 举报

    actionscript3对avm可进行内存操作管理,相比java对jvm可进行的内存操作管理,可不只是逊色,而是太一般了。

    内存管理机制,一般也就是由Garbage Collection(垃圾回收)来实现,简称GC,而actionscript3的GC垃圾回收是由flash player的AVM自动实现的。我们需要清楚了解GC的机制,一是为了减少我们开发出的程序所占的内存,高效健壮运行,二是为了避免内存泄露,乃至崩溃。

    垃圾回收器是运行在后台的一个进程,它释放那些不再被应用所使用对象所占用的内存。不再被应用所使用的对象是指那些不再会被那些活动着(工作着)的对象所“引用”的对象。这里讲的对象都是指非基本类型的对象(非基本类型即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", 所以对象仍然存在
    }

    与GC的实现及应用主要有以下几点:

    1、GC判定一个对象是否还有活动的引用的两种方法:引用计数法、标记清除法
    (1)引用计数法:

    当创建一个对对象的引用后,对象的引用计数就加一,当删除一个引用时,对象的引用技术就减一。如果对象的引用计数为0,那么它被标记为可被GC(垃圾回收器)删除,在avm进行垃圾回收进行的时候即将其删除。

    例如:
    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。

    (2)标记清除法:

    Player从应用的根节点开始(在AS3中通常被称为”根(root)”),遍历所有其上的引用,标记每个它所发现的对象。然后迭代遍历每个被标记的对象,标记它们的子对象。这个过程第归进行,直到Player遍历了应用的整个对象树并标记了它所发现的每个东西。在这个过程技术的时候,可以安全地认为,内存中那些没有被打标记的对象没有任何活动引用,因此可以被安全地释放内存。

    标记清除机制非常准确,但是这种方法需要遍历整个对象结构,因此会增大CPU占用率。因此,Flash Player9为了减少这种开销只是在需要的时候偶尔执行标记清除活动。

    2、弱引用

    Actionscript3有强引用(strong reference)和弱引用的概念(weak reference)。前面提到的引用就属于强引用,而弱引用是会被引用计数器及标记清除策略所忽略,也就是说,弱引用在标记清除过程中不被当做引用,不会阻止垃圾回收其弱引用的对象。

    Actionscript里面的只有两个地方用到弱引用:

    (1)Dictionary

    Dictionary类的构造器使用一个可选择的参数来决定Dictionary实例的键值是否使用弱引用,默认情况下为false了,使用的是强引用,如果设置为true,则使用弱引用:

    var dict:Dictionary = new Dictionary(true); // 使用弱引用

    var obj:Object = new Object();

    dict[obj] = true; // 此时对象obj的引用计数不会增加,为0

    delete obj; // obj会在垃圾回收进行时被回收,释放内存

    (2)addEventListener

    addEventListener方法的最后一个参数useWeakReference:Boolean 是用来设置侦听器为强引用还是弱引用,默认为false,即为强引用。

    // addEventListener(type:String, listener:Function, useCapture:Boolean= false, priority:int = 0, useWeakReference:Boolean = false):void
    addEventListener(MouseEvent.CLICK, clickHandler, false, 0 true); // 使用弱引用

    此时该侦听器会在下一次垃圾回收工作周期进行时被删除收回,节省资源,以免引起内存泄露。但是这样的设置还是有一定的时间延迟的,所以最好的编程习惯应该要在使用完侦听器后调用removeEventListener()移除侦听器。

    3、垃圾回收的时间

    首先,我们必须清楚的是:adobe没有提供api给我们即时地进行垃圾回收。

    网上流传两种关于AVM的GC何时进行垃圾回收:第一种是说具有一定的周期性,第二种是说发生在Flash Player需要另外请求内存之前,并且是当Flash占用的内存紧张到一定程度时才会执行真正的垃圾回收,Flash Player可以重新利用垃圾对象所占用的内存资源,并且可以重新评估需要另外请求的内存数量,也会节省时间。

    我更同意后者,也就是GC进行垃圾回收具有一定的延迟性,不可预知。

    4、强制进行垃圾回收

    网上流传一种利用player的bug来实现强制回收内存,主要是通过人为抛出某种特别的异常会让Flash Player回收内存,代码如下:
    try
    {
    var lc1: LocalConnection = new LocalConnection();
    var lc2:LocalConnection = new LocalConnection();
    lc1.connect( "gcConnection" );
    lc2.connect( "gcConnection" );
    }
    catch (e:Error)
    {

    }
    此方法不是很稳定。最好还是尽量避免对此方法的依赖。

    5、全局变量及局部变量

    (1)无限次触发的Timer会导致内存泄漏。无论无限次触发的 Timer 是否为全局对象,无限次触发的Timer本身以及注册在Timer中的监听器对象都不会被垃圾回收。

  • 相关阅读:
    F
    D
    J
    M
    H
    L
    Android线程之间的通讯
    Java4Android基础学习之异常
    Java4Android基础学习之接口
    Java4Android基础学习之包与访问权限
  • 原文地址:https://www.cnblogs.com/xiayong123/p/3717035.html
Copyright © 2011-2022 走看看