• Flex应用内存泄露分析与诊断1


    [作者:王鹏http://www.bianceng.cn/webkf/Flex/201104/25779.htm]

    引言  

    Flex 采用 ActionScript 语言作为脚本语言,编译后的二进制代码在 FlashPlayer 虚拟机 AVM(Actionscript Virtual Machine)中运行。和 Java 语言类似, AVM 中也有一个垃圾收集器(Garbage Collection),对于不用的对象,隔一段时间会进行 收集并销毁,释放内存。和 C++ 语言相比,程序员不需要时刻关注内存的分配和释放,大大 减轻了负担。但是垃圾收集器不能从根本上解决 Flex 内存泄露的问题,这得从 FlashPlayer 虚拟机的垃圾回收机制谈起。

      FlashPlayer 虚拟机的垃圾回收机制 ,  垃圾收集器采用计数法或标记法来查找需要清除的对象。计数法由于无法检测循环引 用的对象,现在已经很少采用了。重点谈一下标记法。Flex 应用的对象在内存中被映射成树 形结构。这很好理解,每个 Flex 应用总有一个 Application 的入口被称为根节点(Root) ,垃圾收集器从根节点开始遍历每个对象,对可达对象标记为“有效”(有一种 例外就是弱引用,后面的章节详谈)。而在这棵树之外的孤岛对象或者由于循环引用形成的 孤岛对象集合被标记为“无效”,垃圾收集器会在合适的时间销毁这些无效对象 ,完成一次垃圾收集。而垃圾收集器是运行在虚拟机中的一个低优先级的守护进程,为了不 影响性能,它只在必要的时候才运行。例如在向操作系统申请新内存空间的时候,发生异常 的时候等等,因此内存并不是实时回收的。

      Flex 内存泄露的原因:  

    有了垃圾收集器,为什么 Flex 还会产生内存泄露呢?从垃 圾收集器的角度看,对象分为“有效”和“无效”两类;而从 Flex 应用程序的角度看,对象又被分为“有用”和“无用”两类。   举个例子,当程序出现逻辑错误需要提示用户时,Flex 程序构造一个提示框,这时,提示框 是一个“有用”的对象,当用户点击关闭按钮关掉提示框后,提示框就变成 “无用”的对象了,应用程序再也不会用到它(下次出现相同逻辑错误时,程序 又会构造一个全新的提示框)。应用程序认为这个提示框应该被回收掉,但是因为某种原因 ,存在一个从“有效”对象到这个提示框的引用,垃圾收集器显然认为提示框也 是“有效”的。这个“有效”“无用”的提示框便造成了 Flex 的内存泄露。  

       开发过程中造成内存泄露的两种情况  

      了解了 Flex 内存泄 露的原因,从程序员的角度来讲,对于对象引用的混乱管理是造成 Flex 内存泄露的人为因 素。Flex 开发中对于对象的引用分为两种:显示引用和隐式引用,我们分别就这两种情况讨 论一下它们是如何造成内存泄露的。   显示引用   表达式 b=a,创建一个从 b 指 向 a 的引用,当 a 变成无用对象时,由于还存在 b 对它的引用,所以 a 的内存不能被回 收。在开发过程中,全局变量、静态变量、特别是采用单例模式创建的对象,对其他对象的 引用,如果不及时释放都极易造成内存泄露。例如:  

    清单 1. 表达式显示引用  

    public static var staticVar:Object = new Object();
       public function leak():void{
          var chart : AreaChart = new  AreaChart();
          staticVar = chart;
          chart = null;
      } 

    在 leak()方法中,创建了一个临时变量 chart,然后将它赋给静态变量 staticVar,虽然最后将 chart 置为 null,但是由于静态变量对它有一个引用,chart 所占 的内存不会被回收,造成内存泄露。  

    以对象为参数的方法,在方法体内部创建了指向 该对象的引用,没有及时释放而导致内存泄露。将上面的代码变化一下:

     清单 2. 以对象为参数的方法 

    var chart:AreaChart=new AreaChart(); 
    leak(chart);  
    chart = null;   
    ......  
    public static var staticVar:Object = new Object(); 
    
    public function leak(chart: AreaChart):void{ 
    staticVar = chart;   
    } 

     原因和上例相 同,只是发生的位置更加隐蔽。

  • 相关阅读:
    asp.net Ctrl+回车提交
    Request.Form.Keys保存的是什么?
    让iframe子窗体取父窗体地址栏参数(querystring)
    Repeater在无数据记录时显示类似GridView空模板(EmptyDataTemplate)
    jQuery与javascript对照学习(获取父子前后元素)
    internet缓存Temp中的tmp文件
    C#反射遍历一个对象属性(小技巧)
    silverlight序列化反序列化,在c#其他程序反序列化
    Silverlight序列化反序列化(json.net)
    卸载oracle
  • 原文地址:https://www.cnblogs.com/huacw/p/2693787.html
Copyright © 2020-2023  润新知