当前位置: 首页 > news >正文

flex教程:内存使用机巧

 本次flex教程说的是内存使用的一些相关的问题:内存问题向来是程序员十分关注的一个方面,也是体现程序健壮性与否.对于C/C++等类C语言来说,编程人员要对程序使用的内存进行比较谨慎的处理,否则很容易导致内存泄露而使得程序运行缓慢甚至失效.而对于Java等面向对象语言来说,由于采用了一种叫做garbage collection的内存管理机制,极大地将程序员从繁琐的内存管理中解脱出来.但我们不应掉以轻心,如果只是一味的一来这种机制,会使得程序执行效率低下,甚至存在极大的隐患.本文试图从ActionScript的角度来介绍如何正确而高效地处理内存问题,试图给大家提供一种高效率构建富客户端程序的方法.

Flash Player(本身就是一个AVM,AS虚拟机)垃圾回收工作是由垃圾回收器完成的。垃圾回收器是运行在后台的一个进程,它释放那些不再被应用所使用对象所占用的内存。不再被应用所使用的对象是指那些不再会被那些活动着(工作着)的对象所“引用”的对象。在 AS 3中,

对于非基本类型(Boolean, String, Number, uint, int)的对象,在对象之间传递的都是对象引用,而不是对象本身。删除一个变量只是删除了对象的引用,而不是删除对象本身。一个对象可以被多处引用,通过这些不同的引用所操作的都是同一个对象。如下图:

 

虽然将O1设置成null,但内存中它所指向的实例可能并未删除.这取决于垃圾回收器的运行情况.还有一个比较典型的例子是当你使用addChild()往容器中添加了一定数量的可视组件后,又打算使用removeChild()方法来移除容器,虽然从界面上似乎看到可视组件被“删除”了,然而一切并非如你所愿,这些可视组件仍然位于内存中,明显出现了严重的内存泄露,明明发生了我们却置若罔闻!

为此我打算从以下几个方面来细致讨论ActionScript3的内存问题:

 

一.AVM垃圾回收机制

对于非基本类型的对象(基本类型包括Booleanstringnumberintuint),AVM采用了两种方式来判定一个对象是否是活动的引用,以此确定是否应对其内存进行回收

(1)       引用计数法:这是一种简单却比较有效地方式。当创建一个对对象的引用后,对象的引用计数加1,而删除一个引用后,对象的引用计数减1。如果对象的引用计数变为0时,垃圾回收器可以将这个对象从内存中删除。但是当对象间出现了循环引用的情况后,尽管彼此已经不再使用这些对象了,但是它们的引用计数仍然大于大于0,因此无法回收。

(2)       标记清除法:AVM从应用的根节点开始,遍历所有在其上的引用,标记每个它所发现的对象。然后迭代遍历每个被标记的对象,标记它们的子对象。过程结束后,如果内存中出现了没有被标记的对象时,表示该对象已经没有任何活动引用了,因此可以安全将它们“粉碎”。

 

标记清除机制非常精准,但是这种递归执行大大增加了CPU负荷。所以AVM为了减少这种开销只是在需要的时候偶尔执行这种方式来查找无效对象。

注意:上面所说的引用指的是“强引用(strong reference)”,flash player 在标记清除过程中会忽略“弱引用(weakness   reference )”,也就是说,弱引用在标记清除过程

不被当做引用,不会阻止垃圾回收。

默认情况下,AVM执行垃圾回收发生在Flash Player需要另外请求内存之前。也就是只有Flash占用内存紧张到一定程度时,才会触发真正的垃圾回收。我们需要明确两点:A何时真正执行垃圾回收不可预知;B垃圾回收总是在内存吃紧时触发,而非删除对象时。

 

二.内存泄露常见情况

我们在开发中经常会无意识犯以下内存泄露错误:

A.  被全局对象所引用的对象在不需再次使用后却忘记从全局对象中清除对它们的引用。常见的全局对象有 stage,Application,类的静态成员等。

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

C.   通过隐式方式建立的对象之间的引用关系更容易被程序员所忽略,从而导致内存泄露。 最常见的以隐式方式建立对象之间的引用就是“绑定”和“为对象添加事件监听器”。通过测试我们发现“绑定”不会造成内存泄露,对象可以放心地绑定全局对象。而调用addEventListener()方法“为对象添加事件监听器”则可能产生内存泄露,大多数内存泄露都因此而来。

对于解决addEventListener方法可能造成的内存泄露问题,以下情况来使用addEventlistener不会发生:

1. 用弱引用方式注册监听器。 就是调用时将addEventListener的第五个参数置为true

例如:someObject.addEventListener(MouseClick.CLICK, otherObject.handlerFunction, false, 0, true); 

2. 自引用的方式。即:为对象添加的监听处理函数是对象本身的方法。例如: 

this.addEventListener(MouseClick.CLICK, this. handlerFunction); 

子对象引用。即:为子对象添加的监听处理函数是父上对象的方法。例如: 

     private var childObject:UIComponent = new UIComponent;

     addChild(childObject);

     childObject.addEventListener(MouseEvent.CLICK, this.clickHandler);

 

三.内存使用优化建议

1. 被删除对象在外部的所有引用一定要被删除干净才能被系统当成垃圾回收处理掉;
2. 
父对象内部的子对象被外部其他对象引用了,会导致此子对象不会被删除,子对象  不会被删除又会导致了父对象不会被删除;
3. 
如果一个对象中引用了外部对象,当自己被删除或者不需要使用此引用对象时,一定要记得把此对象的引用设置为null;
4. 
本对象删除不了的原因不一定是自己被引用了,也有可能是自己的孩子被外部引用了,孩子删不掉导致父亲也删不掉;
5. 
除了引用需要删除外,系统组件或者全局工具、管理类如果提供了卸载方法的就一定要调用删除内部对象, 否则有可能会造成内存泄露和性能损失;
6. 
父对象立刻被删除了不代表子对象就会被删除或立刻被删除,可能会在后期被系统自动删除或第二次移除操作时被删除;
7. 
如果父对象remove了子对象后没有清除对子对象的引用,子对象一样是不能被删除的,父对象也不能被删除;
8. 
注册的事件如果没有被移除不影响自定义的强行回收机制,但有可能会影响正常的回收机制,所以最好是做到注册的事件监听器都要记得移除干净。
9. 
父对象被删除了不代表其余子对象都删除了,找到一种状态的泄露代码不等于其他状态就没有泄露了,要各模块各状态逐个进行测试分析,直到测试任何状态下都能删除整个对象为止。

 

四.自定义强制垃圾回收类

 所谓强制执行垃圾回收是指通过故意使swf在运行时出错,然后throw出错误,而同时通过catch error来继续运行swf文件。而垃圾回收则会在swf抛出错误的时候,被强制执行一次,以清除内存中无效的数据占用,减少资源的消耗。不过并不是所有的error throw都能触发垃圾回收,而也只局限于某些特定的error,经验发现使用mulinrj参数是比较有效的。

/*
 Programmer:     jinxin
 Build Date:       2010-07-21
 Version:            v1.0
 Summary:        to do garbage recycling work forcefully
    Copyright (C) 2010, MetarNet Technologies Co., Ltd. 
                   All Rights Reserved  
*/
package com.metarnet.controls
{
    import flash.net.LocalConnection;
    import flash.system.System;

    public final class Memory
    {

        public function Memory()
        {
            //TO DO
        }

        public static function gc():void
        {
            try
            {
                new LocalConnection().connect('"mulinrj');
                new LocalConnection().connect('"mulinrj');
            }
            catch (e:*)
            {
            }
        }

        public static function get used():Number
        {
            return System.totalMemory;
        }
    }
}

 

五.Flex Builder3 的内存泄露分析工具 

      Flex Builder3 Pro 带有一个"剖析(Profiler"工具可以用来帮助我们识别内存

泄露。在 Flex Builder3 Pro 的中选择要被"剖析(Profiler"的应用后点击鼠标右键,

在右键菜单中选择“Profile As” 就可以运行"剖析(Profiler"工具来分析所选择的

应用。如下图所示:

 

转自:http://www.jinflex.com/index.php/archives/168

相关文章:

  • 几个简单的数字问题引发的对计算机逻辑的浅显思考,细思有味。新手帖,高手勿砖。...
  • The declared package XX does not match the expected package src.main.java.XX
  • 常用的文件和目录操作命令(转)
  • 算法面试题:寻找数组中重复的数字
  • Java基础——九种基本数据类型,及其封装类
  • 代码同时上传到github和码云
  • maven install出现 找不到符号问题
  • 算法面试题: 斐波那契数列
  • dubbo-springMVC-idea-mac开发环境搭建part3-nexus安装配置(maven私库)
  • 算法面试题:整数反转
  • 算法面试题:多数元素
  • 《改变你一生的108个心理学法则》读书笔记
  • linux 安装jdk1.8并配置环境变量(超简单方便)
  • idea project设置jdk
  • 帝国后台修改密码
  • [数据结构]链表的实现在PHP中
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • flask接收请求并推入栈
  • iOS | NSProxy
  • JSONP原理
  • k8s 面向应用开发者的基础命令
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • React+TypeScript入门
  • swift基础之_对象 实例方法 对象方法。
  • tab.js分享及浏览器兼容性问题汇总
  • vagrant 添加本地 box 安装 laravel homestead
  • 聚类分析——Kmeans
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 模型微调
  • 怎么把视频里的音乐提取出来
  • zabbix3.2监控linux磁盘IO
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​批处理文件中的errorlevel用法
  • # Maven错误Error executing Maven
  • #WEB前端(HTML属性)
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (1)Android开发优化---------UI优化
  • (2020)Java后端开发----(面试题和笔试题)
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (数据结构)顺序表的定义
  • (转)视频码率,帧率和分辨率的联系与区别
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .libPaths()设置包加载目录
  • .mysql secret在哪_MySQL如何使用索引
  • .NET CLR基本术语
  • .NET Framework .NET Core与 .NET 的区别