`
wgcode
  • 浏览: 593423 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

as3.0的垃圾回收机制

 
阅读更多

还是同样的博客,还是同样的作者(Daniel Sidhion),但这次我要翻译的是他的另一篇文章——as3垃圾回收机制。      
      原文链接:http://hub.tutsplus.com/tutorials/understanding-garbage-collection-in-as3--active-4412
      下面进入正文:

      由于这篇文章的作者没有放原例子,所以下面的例子是我根据这篇教程一步步的整理出来,原理简单...看吧!!

       你是否在使用flash应用程序的时候注意过延迟?还不知道那些很酷的flash游戏为什么在你电脑上运行得很慢?你是否想知道更多可能潜在的原因,这篇文章是给你的。

       第一步:一个快的运行

       在我们进入真正的主题之前,你首先需要知道一点在AS3.0中实例与引用是如何工作的。如果你已经读过它,我仍然推荐阅读这微小的一步。所有的知识在你的头脑中都会是新鲜的。

       在as3.0中实例化和实例的引用是不同于大多数人想象中那样的。某些东西的实例化只是代码请求创建一个对象。通常,这种行为通过"new"关键字,但这也存在在当你使用 a literal syntax或者定义参数的函数,例如,这方面的例子如下:

 

// Instantiation through the "new" keyword
new Object();
new Array();
new int();
new String();
new Boolean();
new Date();

// Instantiation through literal syntax
{};
[];
5
"Hello world!"
true

// Instantiation through function parameters
private function tutExample(parameter1:int, parameter2:Boolean):void

   一个对象被创建之后,它仍然保持独立直到某物引用它。为了去做这事情,你一般会创建一个变量,把对象的值赋给变量,让它知道目前被哪个对象控制。不管怎样,当你把一个变量的值赋给另一个变量时,你没有创建一个新的对象。而是为对象创建了另一个连接。看下面的图片:

 



 

 

 

       图片呈现Variable1和Variable2都能控制笑脸(即它们能持有相同的类型)。左边,只有Variable1存在。无论如何,当我们创建并设置Variable2有Variable1相同的值时,我们没有在Variable1和Variable2之间创建一个关联(图片的右上部分),反而我们在笑脸跟Variable2之间创建了一个关联(图片的右下部分)。

       有了这些知识,我们可以跳到垃圾回收机制了。

       第二步:每个"城市"需要一个垃圾回收机制

       显然易见每个应用程序运行都需要一个确定数量的内存,它需要变量去控制值和使用它们。应用程序如何管理不再需要的对象。应用程序应该重复利用这些对象吗?应该删除它们吗?应该储存直到应用程序关闭吗?这三个观点可能发生,但在这里,我们具体谈谈第二个和第三个。

       假想一下,当应用程序初始化创建了很多对象,一旦这个周期结束超过一半被创建的对象仍未使用。它们存在于内存中会发生什么?它们毫无疑问会在内存中占用很多空间,这样就导致了人们所说的延迟。大多数用户不会喜欢这样,所以我们需要避免这样。我们如何编写代码才能使应用程序运行更有效率?答案就在垃圾回收机制中。

       垃圾回收机制是从内存管理形成的。目的是为了清除任何不用并占用系统内存空间的对象。这样的应用程序可以用最小的内存使用来运行。让我们看看它是如何工作的:



  

       当你的程序开始运行,它向系统请求一定量用于程序的内存。程序开始然后任何你需要的信息来填充这些内存。不管怎样,如果内存消耗接近一开始请求的内存,垃圾回收机制就会运行,寻找任何不需要用的对象来清空内存中的一些空间。由于对象搜索的大开销,有些时候这样会导致应用程序的一点延迟。

       图片中,你可以看见内存的峰值。垃圾回收机制会导致内存的峰值和急剧下降,当某些行为使应用程序达到请求内存,清除所有不需要对象。

       第三步:打开swf文件

       现在我们知道垃圾回收机制能为我们做什么,是时候去学习如何编写可以从中获得所有利益的代码了。首先,我们需要知道垃圾回收机制是如何运行的。当对象不能被访问,代码会知道它不能再被使用,所以它会被回收。

       Actionscript3.0通过垃圾回收的根检查可达性。此刻的对象不能通过垃圾回收的根访问,它会变成垃圾。下面你会看到一列它的原则。

       1.包级别的变量和静态变量
       2.局部变量和在一个正在执行的方法的变量或函数范围的变量
       3.从应用程序的主类或显示列表实例化的变量

       为了了解垃圾回收机制是如何处理对象,我们必须编写代码 并检查例子中发生了什么。我将会使用FlashDevelop的AS3项目,但我假设你能使用你想的任何IDE。我创建一个简单的带有一个按钮和文本框的文件。当按钮被点击,一个方法执行。在场景中显示我们想要的文本。

       我们的例子的目的是创建对象,删除它们并检查在它们删除后发生了什么。我们需要一个方法去判断对象是否存活。,所以我们给每一个对象添加一个ENTER_FRAME事件,同时在它们存活时让它们每秒显示一些文本。让我们编写第一个对象!

       我创建一个有趣的笑脸图片对象。每个对象在它的上端会有一个数字。所以我们将第一个对象定义为TheObject1,第二个为TheObject2,所以这样会很容易区分。

  1. private var _theObject1:TheObject1;
  2. private function newObjectSimple1(e:MouseEvent):void
  3. {
  4.     // If there is already an object created, do nothing
  5.     if (_theObject1)
  6.         return;
  7.      
  8.     // Create the new object, set it to the position it should be in and add to the display list so we can see it was created
  9.     _theObject1 = new TheObject1();
  10.     _theObject1.x = 320;
  11.     _theObject1.y = 280;
  12.     _theObject1.addEventListener(Event.ENTER_FRAME, changeTextField1);
  13.      
  14.     addChild(_theObject1);
  15. }
复制代码

      
      第二个对象代码的编写几乎一样。

  1. private var _theObject2:TheObject2;
  2. private function newObjectSimple2(e:MouseEvent):void
  3. {
  4.     // If there is already an object created, do nothing
  5.     if (_theObject2)
  6.         return;
  7.      
  8.     // Create the new object, set it to the position it should be in and add to the display list so we can see it was created
  9.     _theObject2 = new TheObject2();
  10.     _theObject2.x = 400;
  11.     _theObject2.y = 280;
  12.     _theObject2.addEventListener(Event.ENTER_FRAME, changeTextField2);
  13.      
  14.     addChild(_theObject2);
  15. }
复制代码


       代码中,newObjectSimple1()和newObjectSimple2()是鼠标点击按钮事件执行的方法。方法中创建一个对象并显示在舞台上,所以我们知道它被创建了。此外,每个对象侦听了ENTER_FRAME事件。只要它们还存活,就会隔秒显示一个信息。

  1. private function changeTextField1(e:Event):void
  2. {
  3.     // Our example is running at 30FPS, so let's add 1/30 on every frame in the count.
  4.     _objectCount1 += 0.034;
  5.      
  6.     // Checks to see if _objectCount1 has passed one more second
  7.     if(int(_objectCount1) > _secondCount1)
  8.     {
  9.         // Displays a text in the screen
  10.         displayText("Object 1 is alive... " + int(_objectCount1));
  11.          
  12.         _secondCount1 = int(_objectCount1);
  13.     }
  14. }
复制代码
  1. private function changeTextField2(e:Event):void
  2. {
  3.     // Our example is running at 30FPS, so let's add 1/30 on every frame in the count.
  4.     _objectCount2 += 0.034;
  5.      
  6.     // Checks to see if _objectCount2 has passed one more second
  7.     if(int(_objectCount2) > _secondCount2)
  8.     {
  9.         // Displays a text in the screen
  10.         displayText("Object 2 is alive... " + int(_objectCount2));
  11.          
  12.         _secondCount2 = int(_objectCount2);
  13.     }
  14. }
复制代码

<ignore_js_op style="word-wrap: break-word; color: rgb(51, 51, 51); font-family: Tahoma, Helvetica, SimSun, sans-serif;"> 版本1.rar (468.98 KB, 下载次数: 8) 

       第四部:删除对象

       现在我们已经完成了对象的创建。你是否曾经想过你删除一个对象后发生了什么(删除所有的引用)?它会被回收?现在我们测试它。我们创建两个删除按钮,分别对应两个对象。

  1. private function deleteObject1(e:MouseEvent):void
  2. {
  3.     // Check if _theObject1 really exists before removing it from the display list
  4.     if (_theObject1 && contains(_theObject1))
  5.         removeChild(_theObject1);
  6.      
  7.     // Removing all the references to the object (this is the only reference)
  8.     _theObject1 = null;
  9.      
  10.     // Displays a text in the screen
  11.     displayText("Deleted object 1 successfully!");
  12. }
复制代码
  1. private function deleteObject2(e:MouseEvent):void
  2. {
  3.     // Check if _theObject2 really exists before removing it from the display list
  4.     if (_theObject1 && contains(_theObject2))
  5.         removeChild(_theObject2);
  6.      
  7.     // Removing all the references to the object (this is the only reference)
  8.     _theObject2 = null;
  9.      
  10.     // Displays a text in the screen
  11.     displayText("Deleted object 2 successfully!");
  12. }
复制代码


<ignore_js_op style="word-wrap: break-word; color: rgb(51, 51, 51); font-family: Tahoma, Helvetica, SimSun, sans-serif;"> 版本2.rar (469.51 KB, 下载次数: 15) 
       如你所见,如果你点击"Create Object1"然后点击"Delete Object1",什么也没发生!我们可以说代码运行了,因为文本出现在舞台上,但为什么对象没有被删除?对象仍在这里因为这没有完全删除。当我们清理所有引用,我们告诉代码使它成为垃圾,但垃圾回收机制从未运行。记住垃圾回收机制只会在当前内存消耗接近一开始程序请求的内存。但我们该如何测试它?

       我肯定不会去写一大片代码用无用的对象去填满应用程序直到内存消耗过大。我们将使用一个当前Adobe不支持的方法。根据Grant Skinner(http://www.gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html)的文章,强制运行垃圾回收机制。这个方法,我们触发一个简单的方法并看到在运行时发生什么。从现在开始,我会把垃圾回收机制叫为GC。

  1. private function forceGC(e:MouseEvent):void
  2. {
  3.     try
  4.     {
  5.         new LocalConnection().connect('foo');
  6.         new LocalConnection().connect('foo');
  7.     }
  8.     catch (e:*) { }
  9.      
  10.     // Displays a text in the screen
  11.     displayText("----- Garbage collection triggered -----");
  12. }
复制代码


       这个简单的方法,只是创建了两个LocalConnection()对象,意味着强制运行GC,我不推荐在严格的应用程序中使用这个方法。如果你是做测试,这样没有真正的问题。但如果是分配给其他人的应用程序,这不是一个好用的方法,以后会引起不可预料的效果。

 版本3.rar (469.89 KB, 下载次数: 8) 

       删除一个对象后触发GC,这真正的删除了这个对象!注意,如果你不删除对象但触发了GC,什么也不会发生,因为对象还有一个引用。现在,我们尝试一个对象保持两个引用并删除其中一个。

       第五步:创建另一个引用

       现在我们证实了GC工作后是我们想要的效果。让我们尝试其他:为一个对象(Object1)连接另一个引用并删除原型。

  1. private function saveObject1(e:MouseEvent):void
  2. {
  3.     // _onSave is a Boolean to check if we should link or unlink the reference
  4.     if (_onSave)
  5.     {
  6.         // If there is no object to save, do nothing
  7.         if (!_theObject1)
  8.         {
  9.             // Displays a text in the screen
  10.             displayText("There is no object 1 to save!");
  11.              
  12.             return;
  13.         }
  14.          
  15.         // A new variable to hold another reference to Object1
  16.         _theSavedObject = _theObject1;
  17.          
  18.         // Displays a text in the screen
  19.         displayText("Saved object 1 successfully!");
  20.          
  21.         // On the next time this function runs, unlink it, since we just linked
  22.         _onSave = false;
  23.     }
  24.     else
  25.     {
  26.         // Removing the reference to it
  27.         _theSavedObject = null;
  28.          
  29.         // Displays a text in the screen
  30.         displayText("Unsaved object 1 successfully!");
  31.          
  32.         // On the next time this function runs, link it, since we just unlinked
  33.         _onSave = true;
  34.     }
  35. }
复制代码


       如果我们现在测试,我们会发现如果我们创建Object1,然后保存它,删除它和强制执行GC,什么也不会发生。那是因为,即使我们删除原本的对象的关联,还有另一个引用。这使它不符合垃圾回收的条件。这基本上是所有你需要知道的关于GC。在这之后,我们该如何应用它到我们当前环境中?我们如何运行这知识去预防我们的程序运行缓慢?第六步将会介绍给我们:

 版本4.rar (470.41 KB, 下载次数: 10) 

       第六步:使你的代码有效率

       现在是最好的部分:使你的代码与GC高效地工作!这一步会提供很有用的信息。首先,我想介绍一个新的方法在你的应用程序里创建你的对象。这很简单,但需要有效地与GC合作。这个方法介绍两个简单的类。

       这个方法的思想是实现一个方法-名字叫destroy(),每一个你创建的对象,在这个对象完成工作的时候调用它。这个方法包含了所有必要的代码去删除所有对象的引用(不包括用于调用方法的引用),所以你要确保对象完全离开你的应用,容易识别GC。这样做的原因的解释在下一步。下面看一下这个方法的大致代码。

  1. // Create this in every object you use
  2. public function destroy():void
  3. {
  4.     // Remove event listeners
  5.     // Remove anything in the display list
  6.     // Clear the references to other objects, so it gets totally isolated
  7.      
  8. }
  9. // ...
  10. // When you want to remove the object, do this:
  11. theObject.destroy();
  12. // And then null the last reference to it
  13. theObject = null;
复制代码


       在这个方法,你会清除对象的所有东西,所以它完全与程序分离。在这之后,这将会更容易让GC定位和删除这个对象。现在看看一些最大内存错误发生的情况。

       1.只用于执行一个段时间的对象:你需要注意这个,它们可以消耗大量内存。这些对象只存在一段时间(例如,一个存储值的函数运行)和它们不经常被访问。记得删除它们的所有引用在你完成它们之后。否则,你的程序中会有很多这样的对象。如果你创建了很多它们的引用,你必须通过destroy()方法清除每一个。

       2.离开显示列表的对象:如果你想删除一个对象经常从显示列表中删除它。显示列表是垃圾回收机制的最根本。所以当你删除对象时保持你的对象远离它是很重要的。

       3.舞台,父亲和根引用:如果你喜欢大量的这些特征,记住当你完成时删除它们。如果你有大量有这样的引用的对象,你会有麻烦!

       4.时间侦听:有时让你的对象接受回收的是一个事件侦听引用。记住删除它们,或令它们成为弱引用,如果需要。

       5.数组(Array)和向量(Vectors):有时你的数组和向量会有其他对象,在它们离开引用时你可能不知道。注意数组和向量。


       第七步:

       虽然与GC一起工作是顺利的,但不完美。你必须注意你正在做得事情,否则你的程序会发生坏事情。我想证明一个问题,你不需要跟随所有必要的步骤而使你的代码更合适的与GC工作。

       有时候如果你不把一个对象的所有引用清除,你可能有这个问题,尤其是你把很多对象连接在一起。有时,一个简单的引用的离开足以让这发生:你的所有对象的引用的岛屿(island),所有对象与其他都有联系,不允许GC删除它们。

       当GC运行时,会执行两个简单任务去检查要删除的对象。计算每个对象有多少个引用。所有对象有0个引用的同时回收。另一个任务是,检查那堆互相连接的对象,但不能被访问,如此浪费内存。



  
       如你所见,绿色对象不能被延伸,但它们的引用计数为1。GC执行第二个任务检查这一块对象并删除它们全部。无论如何,当这一块太多,GC“放弃”检查和假设对象能延伸。



  
       这是引用的岛屿(island)。这会花费系统很大量的内存。同时因为它的复杂而不会被GC回收。这听起来很糟糕,对吧?这很容易避免,但需确保清除对象的一切引用。然后这可怕的事情就不会发生了。

       总结:

       现在到这里了。我们学习到为了减少延迟和内存使用让我们的代码更有效率。为了做到这样,我们必须了解在as3中对象的引用是如何工作的,如何使GC与我们的应用程序更有效地合作。当这样做的时候我们必须小心,否则它会变得更加棘手和缓慢!

       我希望你喜欢这个简单的技巧。

 

  • 大小: 53.4 KB
  • 大小: 22.9 KB
  • 大小: 21.9 KB
  • 大小: 30.8 KB
分享到:
评论

相关推荐

    as3.0做的连连看

    AS3.0提供了垃圾回收机制,但开发者仍需注意避免内存泄漏。此外,合理地缓存对象、减少不必要的计算以及适时的资源释放都是提高游戏性能的重要手段。 7. **用户体验** 为了提供良好的用户体验,游戏应具有响应迅速...

    AS 3.0帮助文档

    6. **垃圾回收机制**:AS 3.0引入了自动垃圾回收,开发者无需手动管理内存,降低了编程复杂性。 7. **高性能的虚拟机**:Adobe Flash Player和Adobe AIR为AS 3.0提供了高效的虚拟机,使得运行速度显著提升。 **AS ...

    Flash as3.0制作的拼图小游戏源码。

    这个编程版本在2006年推出,相对于之前的AS2.0,它有着显著的性能提升、类型检查和垃圾回收机制等改进,极大地提高了开发效率和代码质量。 在这款“Flash as3.0制作的拼图小游戏源码”中,我们可以推测出几个关键的...

    AS3.0简单相册,适合初学者

    了解如何优化代码和使用垃圾回收机制是提升应用性能的关键。 10. **调试和测试**:使用Flash Professional或FlashDevelop等开发工具提供的调试器,可以帮助查找和修复代码中的错误。 通过学习和实践这个"AS3.0简单...

    as3.0实现的一个碰撞类小游戏

    AS3.0提供了垃圾回收机制,但过多的内存分配和对象创建可能导致性能下降。因此,合理的对象池设计和复用策略可以减少不必要的资源消耗。 为了提供更好的用户体验,游戏往往需要有音效和动画。AS3.0支持`Sound`和`...

    AS3.0背包功能

    10. **代码优化**:为了提供流畅的用户体验,开发者可能会关注性能优化,例如减少不必要的计算、缓存常用数据、合理使用垃圾回收机制等。 通过以上分析,我们可以看出AS3.0背包功能不仅涉及基本的编程技术,还涵盖...

    AS+3.0+学习文档精华版(二).rar

    5. **垃圾回收机制**:AS 3.0 实现了自动垃圾回收,解决了内存管理问题,程序员无需手动释放内存。 6. **Display List**:AS 3.0 的显示列表是一套层次化的容器,用于管理舞台上的视觉元素,如MovieClip、Sprite等...

    Java转AS3.0工具 java类转换工具

    6. **内存管理**:Java使用垃圾回收机制,而AS3.0的内存管理也依赖于垃圾回收,但两者的具体实现和策略可能有差异。 7. **语法**:两者语法上有明显区别,如AS3.0中的“::”操作符用于访问静态成员,而在Java中是...

    FLASH AS 3.0 3D螺旋相册

    AS3的事件模型、垃圾回收机制和优化的虚拟机都极大地提升了程序的性能和稳定性。 2. **3D图形处理**:在AS3中,可以使用“flash.display”库中的类,如“Sprite”和“Shape”,来创建基本的3D几何形状。通过矩阵...

    AS+2.0与AS+3.0对照速查表

    13. **垃圾回收机制**: - AS 3.0实现了自动垃圾回收,无需手动管理内存,而AS 2.0则需要开发者自行管理。 "AS 2.0与AS 3.0对照速查表.exe"文件可以帮助开发者快速查找两个版本间的语法差异,以便在从AS 2.0迁移到...

    as3.0学习手册

    - **性能优化**: AS3 在运行时具有较高的执行速度,得益于其垃圾回收机制和高效的编译器。 - **内存管理**: AS3 使用自动垃圾回收机制来管理内存,减少了内存泄漏的风险。 - **事件驱动模型(Event-driven model)**...

    AS3.0制作的生日蛋糕

    在性能优化方面,AS3.0引入了强类型和垃圾回收机制,这有助于减少内存泄漏并提高代码执行效率。开发者需要合理地组织代码,避免不必要的计算和内存占用,确保动画流畅运行。 总之,通过"AS3.0制作的生日蛋糕"这个...

    AS3.0人机互动五子棋

    - AS3.0中的垃圾回收机制可能导致内存波动,因此在处理大量对象(如棋子)时,应避免不必要的内存分配和对象创建。 9. **响应式设计**: - 考虑到不同屏幕尺寸,确保棋盘和棋子的大小能适应各种设备,提供良好的...

    AS3.0教程,中文版的

    了解内存管理、垃圾回收、代码优化技巧等,可以避免性能瓶颈。 教程“AS3_Cookbook中文版.pdf”可能包含了这些主题的实践示例和技巧,帮助开发者解决实际问题,提升技能。通过学习此教程,你可以更好地掌握AS3.0和...

    AS3.0语言在Flash编程中的应用

    - **ActionScript 3** (AS3): 是ActionScript的一个重要版本,显著提高了性能,并引入了许多新特性,如面向对象编程(OOP)支持、垃圾回收机制等。 - **AS3的优点**: - 性能大幅提升。 - 更强大的OOP支持。 - ...

    flash as3.0代码优化

    - 当不再使用某个对象时,将其设置为 `null`,帮助垃圾回收器及时释放内存。 - 使用 `BitmapData` 进行位图操作时,注意锁解锁机制,确保数据安全。 ### 4. CPU资源管理 - 移除舞台上的 `DisplayObject` (使用 `...

    ActionScript3.0 参考概述

    6. **垃圾回收机制**:AS3.0引入了自动垃圾回收机制,开发者无需手动管理内存,当对象不再被引用时,系统会自动释放其占用的内存。 7. **错误处理**:通过`try...catch...finally`语句块,AS3.0提供了完善的错误...

    ActionScript3.0 中文版

    13. 性能优化:AS3.0的垃圾回收机制和优化编译器提高了运行效率,使得编写高性能应用成为可能。 这个中文版的API文档还涵盖了ActionScript3.0的其他关键概念,如包、命名空间、访问修饰符、构造函数、静态成员,...

    flash ActionScript.3面试题1

    AS3.0 使用了一种称为“引用计数”的垃圾回收机制。它自动管理内存分配和释放。当对象不再被引用时,它的引用计数降至零,这时对象会被标记为可回收,并最终由垃圾回收器释放其占用的内存空间。这种机制有助于减少...

    ActionScript3.0

    5. **垃圾回收机制**:AS3.0 包含了一个自动垃圾回收机制,负责管理内存,开发者无需手动释放内存。这简化了内存管理,降低了内存泄漏的风险。 6. **XML和JSON支持**:AS3.0 提供了内置的XML和JSON类,便于数据交换...

Global site tag (gtag.js) - Google Analytics