zoukankan      html  css  js  c++  java
  • 【转】Flash Player的垃圾内存回收机制:能否强制回收?

    在Adobe Flash Player 10中,AS3的内部垃圾回收机制是怎样的?程序员可以强制FP回收内存吗?答案是否定的,但有方法。

     强制垃圾内存回收的代码

    AS3程序员没有办法强制Flash Player进行垃圾回收。

    MoonSpirit在天地会撰写过一篇关于强制垃圾回收的文章:[as hack技术]垃圾回收机强制执行。文中例证,使用LocalConnection连接非法地址,并捕获导常,可以强制进行垃圾回收。sban在MoonSpirit的基础上,简单修改了一下代码,如下:

    package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.net.LocalConnection;

    /**
    *
    * @author sban http://sban.biz/
    * 修改自MoonSpirit的强制垃圾回收测试代码
    */
    public class GarbageCollectionTest extends Sprite {
    private const SQR_AMOUNT :
    int = 10000; //方块数量
    private var _container_sp : Sprite;//容器sprite
    private var _sqrList: Array;//所有方块的引用

    //强制垃圾回收使用的对象
    private var conn1 :LocalConnection;
    private
    var conn2 :LocalConnection;

    public
    function GarbageCollectionTest() {
    init( );
    }

    private
    function init( ) : void{
    _container_sp
    = new Sprite( );
    addChild(_container_sp);
    //initNoBitmapDataView( );//峰值4111K,手动回收两次变为9K
    initBitmapDataView( );//峰值14K,最小为14K,手动回收基本无变化
    }

    //初始化 通过通常手段 显示
    private function initNoBitmapDataView( ) : void {
    layoutTenThousandSqr( );

    unLayoutTenThousandSqr( );
    _sqrList
    = null;
    removeChild(_container_sp);
    _container_sp
    = null;
    }

    //初始化 通过BitmapData快照 显示
    private function initBitmapDataView( ) : void {
    layoutTenThousandSqr( );

    unLayoutTenThousandSqr( );
    _sqrList
    = null;
    removeChild(_container_sp);
    _container_sp
    = null;

    doClearance( );
    }

    private
    function layoutTenThousandSqr( ) : void {
    _sqrList
    = new Array( );
    for(var i : int = 0; i < SQR_AMOUNT; i++){
    _sqrList.push(
    new Sprite());
    _sqrList[i].graphics.beginFill(
    0xff0000);
    _sqrList[i].graphics.drawRect(
    0,0,100,100);
    _sqrList[i].graphics.endFill();
    _container_sp.addChild(_sqrList[i]);
    }
    }

    //不显示
    private function unLayoutTenThousandSqr( ) : void {
    for(var i : int = 0; i < SQR_AMOUNT; i++){
    _container_sp.removeChild(_sqrList[i]);
    delete _sqrList[i];
    }
    }

    //精髓,垃圾回收机强制调用
    private function doClearance( ) : void {
    trace(
    "clear");
    try{
    conn1
    = new LocalConnection();
    conn1.connect(
    "sban garbage collection 1");
    conn2
    = new LocalConnection();
    conn2.connect(
    "sban garbage collection 1");
    }
    catch(e :*){}
    finally{
    conn1
    = null;
    conn2
    = null;
    }
    }
    }
    }

    首先sban不调用doClearance方法,手动单击两次FB的“运行垃圾回收器”按钮(为什么要两次,后面解答),内存二下从4111K降到了9K!如下图所示,雷人吧。

    image

    然后呢,sban调用doClearance方法,这次无论是否手动回收,内存占用无变化,如下图所示,这说明doClearance方法已经强制了垃圾内存回收,它作用了!

    image

    那么,为什么创建两次没用的LocalConnection可以强制回收内存呢?

    3. AS3垃圾内存回收机制

    在Flash Player初始化运行时,会向操作系统申请一大块内存,如果程序很小,有可能根本用不了这么多内存,但FP在开始时不考虑这些,大多数情况下,第一次申请的内存总是不够用的。第一次申请的内存大小,与操作系统、浏览器环境有关。

    当Flash Player发现已经申请的内存不够用时,它会再向操作系统申请一大块内存。但在申请之前,请注意,FP会尝试进行垃圾内存回收。那么它是如何回收的呢?

    Flash Player在内部使用懒惰式引用计数回收方案进行垃圾内存回收,懒惰式指:FP并不会一次把所有可以回收的对象全部回收,它一次仅会回收一部分,如果内存不够用,它会向操作系统申请,如果系统无内存了,它会再次回收,如果全部回收了仍不够用,Game Over!引用计数指:FP在内部给每个对象标记一个记号,当没有任何对象引用此对象时,它即是可以被回收的;如果一个容器内有许多相互关联的对象,当把这个容器从显示列表中移除,并且置为null后,它也是可以被回收的。

    在小节2中,sban问到为什么要手动单击两次“运行垃圾回收器”按钮,这是由于FP垃圾回收机制的懒惰性造成的。

    在清楚了FP的内部垃圾回收机制之后,我们便可以回答,为什么创建两次没用的LocalConnection,并且连接并不存在的地址,故意抛出异常然后捕获,可以强制垃圾回收呢?因为,在AS3中LocalConnection是比较占用内存的对象,两次创建该类对象并尝试进行连接的内存开销大小足以请Flash Player重新向操作系统申请内存,而在申请之前,FP会尝试回收。原理即是这么简单,非独使用LocalConnection可以,其它较耗内存的对象也可以。

    sban 2008年5月 北京。转载请注明作者出处,非商用。本文属于《AS3 Expert》。

  • 相关阅读:
    XML错误信息Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-4.0.xsd). For more information, right click on the message in the Problems View ...
    Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
    maven创建web报错Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins:maven-compiler-plugin:maven-compiler-plugin:3.5.1:runtime Cause: error in opening zip file
    AJAX跨域
    JavaWeb学习总结(转载)
    JDBC学习笔记
    Java动态代理之JDK实现和CGlib实现
    (转)看懂UML类图
    spring boot配置使用fastjson
    python3下django连接mysql数据库
  • 原文地址:https://www.cnblogs.com/cos2004/p/1869421.html
Copyright © 2011-2022 走看看