`
wangleifire
  • 浏览: 508991 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

内存回收

    博客分类:
  • FLEX
阅读更多

先了解下回收的原理,如果觉得麻烦,可以直接看最后的方法
摘自:http://www.duzengqiang.com/blog/article.asp?id=245

AS3垃圾收集器不再支持自动为你收集垃圾等假设。也就是说Flash开发者转到ActionScript 3.0之后需要对关于垃圾收集如何工作以及如何编程使其工作更加有效具备较深入的理解。没有这方面的知识,即使创建一个看起来很简单的游戏或应用程序也会 出现SWF文件内存泄露、耗光所有系统资源(CPU/内存)导致系统挂起甚至机器重启。

要理解如何优化你的ActionScript 3.0代码,你首先要理解垃圾收集器如何在Flash Player 9中工作。Flash有两种方法来查找非活动对象并移除它们。本文解释这两种技术并描述它们如何影响你的代码。

本文结尾你会找到一个运行在Flash Player9中的垃圾收集器模拟程序,它生动演示了这里解释过的概念。

关于垃圾收集器

垃圾收集器是一个后台进程它负责回收程序中不再使用的对象占用的内存。非活动对象就是不再有任何其他活动对象引用它。为便于理解这个概念,有一点非常重 要,就是要意识到除了非原生类型(Boolean, String, Number, uint, int除外),你总是通过一个句柄访问对象,而非对象本身。当你删除一个变量其实就是删除一个引用,而非对象本身。

以下代码很容易说明这一点:


            ActionScript 代码
            
            
            
                // create a new object, and put a reference to it in a:  
                var a:Object = {foo:"bar"}  
                // copy the reference to the object into b:  
                var b:Object = a;  
                // delete the reference to the object in a:  
                delete(a);  
                // check to see that the object is still referenced by b:  
                trace(b.foo); // traces "bar", so the object still exists.  
            
            
            如果我改变上述示例代码将b也删除,它会使我创建的对象不再有活动引用并等待对垃圾收集器回收。ActionScript 3.0 垃圾回收器使用两种方法定位无引用的对象 : 引用计数法和标识清除法。

引用计数法

引用计数法是一种用于跟踪活动对象的较为简单的方法,它从 ActionScript 1.0开始使用。当你创建一个指向某个对象的引用,该对象的引用计数器加1;当你删除该对象的一个引用,该计数器减1。当某对象的计数器变成0,该对象将被标记以便垃圾回收器回收。

这是一个例子:


            ActionScript 代码
            
            
            
                var a:Object = {foo:"bar"}  
                // the object now has a reference count of 1 (a)  
                var b:Object = a;  
                // now it has a reference count of 2 (a & b)  
                delete(a);  
                // back to 1 (b)  
                delete(b);  
                // the reference count down is now 0  
                // the object can now be deallocated by the garbage collector  
            
            
            引 用计数法简单,它不会非CPU带来巨大的负担;多数情况下它工作正常。不幸地是,采用引用计数法的垃圾回收器在遇到循环引用时效率不高。循环引用是指对象 交叉引用(直接、或通过其他对象间接实现)的情况。即使应用程序不再引用该对象,它的引用计数器仍然大于0,因此垃圾收集器永远无法收集它们。下面的代码 演示循环引用是怎么回事:


            ActionScript 代码
            
            
            
                var a:Object = {}  
                // create a second object, and reference the first object:  
                var b:Object = {foo:a};  
                // make the first object reference the second as well:  
                a.foo = b;  
                // delete both active application references:  
                delete(a);  
                delete(b);  
            
            
            上 述代码中,所有应用程序中活动的引用都被删除。我没有任何办法在程序中再访问这两个对象了,但这两个对象的引用计数器都是1,因为它们相互引用。循环引用 还可以更加负责 (a 引用 c, c引用b, b引用a, 等等) 并且难于用代码处理。Flash Player 6 和 7的XML对象有很多循环引用问题: 每个 XML 节点被它的孩子和父亲引用,因此它们从不被回收。幸运的是Flash Player 8 增加了一个叫做标识-清除的新垃圾回收技术。

标识-清除法

ActionScript 3.0 (以及 Flash Player 8) 垃圾回收器采用第2种策略标识-清除法查找非活动对象。Flash Player从你的应用程序根对象开始(ActionScript 3.0中简称为root)直到程序中的每一个引用,都为引用的对象做标记。

接下来,Flash Player遍历所有标记过的对象。它将按照该特性递归整个对象树。并将从一个活动对象开始能到达的一切都标记。该过程结束后,Flash Player可以安全的假设:所有内存中没有被标记的对象不再有任何活动引用,因此可以被安全的删除。图1 演示了它如何工作:绿色引用(箭头)曾被 Flash Player 标记过程中经过,绿色对象被标记过,白色对象将被回收。



Figure 1. Flash Player采用标记清除方法标记不再有活动引用的对象

标记-清除法非常准确。但是,由于 Flash Player 遍历你的整个对象结构,该过程对CPU占用太多。Flash Player 9 通过调整迭代标识-清除缩减对CPU的占用。该过程跨越几个阶段不再是一次完成,变成偶尔运行。

延期(执行)垃圾回收器和不确定性

Flash Player 9垃圾回收器操作是延期的。这是一个要理解的非常重要的概念:当你的对象的所有引用删除后,它不会被立即删除。而是,它们将在未来一个不确定的时刻被 删除(从开发者的角度来看)。垃圾收集器采用一系列启发式技巧诸如查看RAM分配和内存栈空间大小以及其他方法来决定何时运行。作为开发者,你必须接受这 样的事实:不可能知道非活动对象何时被回收。你还必须知道非活动对象将继续存在直到垃圾收集器回收它们。所以你的代码会继续运行(enterFrame 事件会继续)、声音会继续播放、装载还会发生、其它事件还会触发等等。

下面介绍回收的有效方法:

由这副图可以看出来 当你的类中包含的对象越多,嵌套越深,对象越复杂,系统回收发费时间就越长。而我们如果自行把这些对象与嵌套拆开来,使得每个复杂的对象变成一个一个的非常小的对象,那么回收所花的时间就会大大减少了。所以我们写完类,记得给类加上一个垃圾回收器,如:
package buildworld
{
       import flash.display.Sprite;
       import mypkg.MapBlock;
       public class Map extends Sprite
       {
              private var map:Array = new Array();
              private var mapName:String = "map1";
              
              public function Map(nw:int,nh:int):void
              {
                     this.createMap();
              }
              public function createMap():void
              {
                     for(var h = 0;h < this.nHeight;h++)
                     {
                            this.map[h] = new Array();
                            for(var l = 0;l < this.nWidth;l++)
                            {
                                                                                //MapBlock是个类,
                                   this.map[h][l] = new MapBlock();
                                   
                            }
                     }
              }
              //垃圾回收器
              public function gc():void
              {
                     for(var h = 0;h < this.nHeight;h++)
                     {
                            for(var l = 0;l < this.nWidth;l++)
                            {
                                   
                                   this.removeChild(this.map[h][l]);
                                   this.map[h][l].gc();//调用MapBlock中的垃圾回收器
                                   this.map[h][l] = null;
                            }
                     }
                     mapName = null;
              }
       }
}
那么最终进行垃圾回收就方便多了。

不知道大家还有更好的方法没?

分享到:
评论

相关推荐

    C#中实现内存回收

    本程序"MemoryCollectTest"旨在帮助开发者理解和实践如何在C#中强制触发内存回收。 首先,我们需要了解.NET内存管理的基本概念。.NET中的内存分为堆和栈两部分。栈主要用于存储基本类型和引用,而堆则用于存储对象...

    IIS站点内存回收 ,导致Session被清空

    本文将深入探讨"IIS站点内存回收导致Session被清空"的问题,并提供相应的解决方案。 IIS(Internet Information Services)是微软提供的一个用于发布Web内容的服务器平台。在运行过程中,IIS通过应用程序池...

    安卓kernel 内存回收机制

    不过,既然标题是“安卓kernel 内存回收机制”,那么我可以根据这个主题,详细说明安卓内核内存回收机制的知识点。 安卓操作系统是基于Linux内核构建的,Linux内核具有强大的内存管理能力,安卓系统在此基础上...

    深入理解.NET内存回收机制

    ### 深入理解.NET内存回收机制 #### 一、引言 在.NET框架中,内存管理是一项核心功能,它负责自动地管理应用程序所使用的内存资源。与传统的手动内存管理方式(如C++中的new/delete操作)不同,.NET通过引入垃圾...

    内存管理 c++ C++内存回收

    本文将深入探讨C++中的内存管理,包括内存回收、内存泄漏以及相关的检测工具。 首先,我们要理解C++的内存层次结构,主要包括栈内存(Stack)、堆内存(Heap)、静态存储区(Static)和常量存储区(ReadOnly)。栈...

    C++实现自动内存回收

    为了解决这些问题,一些高级语言如Java和Python提供了自动内存回收机制,即垃圾回收(Garbage Collection)。在C++中,虽然没有内置的垃圾回收机制,但可以通过特定的设计模式和库来实现类似的功能。 《The Art of ...

    操作系统内存回收与分配

    本篇文章将深入探讨“操作系统内存回收与分配”这一主题,帮助读者理解这一核心概念。 内存分配是指在程序运行时为它分配所需的内存空间,而内存回收则是指当程序结束或不再需要某块内存时,将其归还给系统以便再次...

    VC 内存操作:内存回收及分配空间.rar

    VC 内存操作:内存回收及分配空间的实例代码,根据运行后所返回的信息,可看出程序再分配内存后,又重新收回了内存,从分配到释放的一个过程,先处理剩余空间然后修改原来的节点信息,把剩余的空间化为一个节点并连...

    系统 内存 回收 软件

    "系统内存回收软件"就是针对这一需求而设计的工具,其主要目的是提高计算机运行效率,特别是对于那些配置较低的老式电脑,这类软件能显著提升用户体验。 首先,我们需要理解内存(RAM)在计算机中的作用。内存是...

    .NET内存回收机制

    .NET内存回收机制是.NET框架核心组成部分之一,主要负责管理应用程序的内存分配和释放,从而避免内存泄漏问题。这一机制由垃圾回收器(Garbage Collector,简称GC)执行,使得程序员无需手动管理内存,提高了开发...

    操作系统内存回收.doc

    这种方式提高了内存利用率,但也引入了内存回收的问题,即如何有效地释放不再使用的内存以供后续使用。 内存回收主要关注四个基本情况: 1. **内存分配后未使用**:程序分配了内存但未实际使用,这部分内存应当被...

    C# 内存回收方法

    C# 内存回收C# 内存回收C# 内存回收C# 内存回收C# 内存回收

    动态内存分配以及内存回收算法的实现

    ### 动态内存分配以及内存回收算法的实现 #### 实验背景与意义 在现代计算机系统中,内存管理是一项至关重要的任务。合理的内存管理不仅能够提高系统的运行效率,还能够确保程序的稳定性和安全性。本实验旨在通过...

    Flash强制垃圾内存回收测试

    本文将围绕“Flash强制垃圾内存回收测试”这一主题进行深入探讨,结合提供的标签“源码”和“工具”,我们将讨论Flash平台上的内存管理机制,特别是如何进行垃圾回收(Garbage Collection, GC)以及如何通过源码进行...

    Java的内存回收

    Java的内存回收, 及时的回收内存资源,更有利于程序的稳定性

    用首次适应算法模拟内存的分配和回收

    在内存回收方面,我们需要将已分配给进程的内存块回收到空闲区表中,并合并相邻的空闲内存块,以减少碎片的产生。为了实现这一任务,我们需要维护着一个已分配分区表,记录着所有已分配给进程的内存块的信息。 实验...

    java JVM 内存回收

    Java虚拟机(JVM)的内存回收,也称为垃圾收集(GC),是Java语言特性的重要组成部分,用于自动管理内存,释放不再使用的对象所占用的空间。虽然Java语言本身并不强制要求JVM实现GC,但现代JVM如Oracle的HotSpot JVM...

Global site tag (gtag.js) - Google Analytics