专栏首页python3AS3 内存回收机制

AS3 内存回收机制

       AS3相对于以前版本的功能增强了很多,在赋予它重任时,同时也要它付出代价:垃圾收集器不再支持自动为你收集垃圾。本文中,我为大家整理了一些资料。首先,我们先来了解下垃圾收集器是个什么东西?

       (1)关于垃圾收集器

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

(2)AS3的内存机制的方法:

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

     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);   // down to 0, the object can now be deallocated by the GC

<b>引用计数法简单,它不会非CPU带来巨大的负担;多数情况下它工作正常。不幸地是,采用引用计数法的垃圾回收器在遇到循环引用时效率不高。循环引用是指对象交叉引用(直接、或通过其他对象间接实现)的情况。即使应用程序不再引用该对象,它的引用计数器仍然大于0,因此垃圾收集器永远无法收集它们。下面的代码演示循环引用:

     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, 等等) 并且难于用代码处理。FlashPlayer 6 和 7的XML对象有很多循环引用问题: 每个 XML 节点被它的孩子和父亲引用,因此它们从不被回收。幸运的是FlashPlayer 8 增加了一个叫做标识-清除的新垃圾回收技术。

<c>标识-清除法 ActionScript3.0 (以及FlashPlayer 8) 垃圾回收器采用第2种策略标识-清除法查找非活动对象。FlashPlayer从你的应用程序根对象开始(ActionScript3.0中简称为root)直到程序中的每一个引用,都为引用的对象做标记。 接下来,FlashPlayer遍历所有标记过的对象。它将按照该特性递归整个对象树。并将从一个活动对象开始能到达的一切都标记。该过程结束后,FlashPlayer可以安全的假设:所有内存中没有被标记的对象不再有任何活动引用,因此可以被安全的删除。图1 演示了它如何工作:绿色引用(箭头)曾被FlashPlayer 标记过程中经过,绿色对象被标记过,白色对象将被回收。

(3)AS3的内存机制的特点:

          1.  自动内存回收时间不确定。

          2.  当一个对象存在被其他对象引用时,这个对象不会被内存回收。

          3.  当一个流对象被加载,这个被加载的对象及已经占用了内存。

          4.  当一个可视化对象被声明,但没有添加到画面是占用部分内存,加到displayObject上后,占用全部该对象对象全部内存。

         5.  当加载重复对象,例如 加载100个同样的 XX.swf ,如果仅是加载,完成后没有引用,那么内存变化规律,波浪型的。如果某个时间内存回收。那么最后留在内存中的应该是大小近似于加载1个 XX.swf (比1个XX.swf 要大些),从此可以推理出,要是不同的东西被加载,那么最后即便是没有内存漏洞,在一定条件下常用的东西内存中可能也会至少保存每一个不同的东西。经我测试好像是这样的。(测多了可能还会有新发现呢)

         6.  引用的包括

         1)  对对象的存储: 例如 使用一个数组保存 某些对象,那么数组不释放,对象不可能释放

         2)  对事件的监听: 例如 监听过程实际上是使用一个对象保存关键字和关键字关联的事件,对事件关键字,查找然后找出对应的关联function。以下是as2代码。

         3)  强制回收方式,自动内存回收时间不确定,使用特殊的方法,该方法实际上触发一个错误引起资源回收,使无用的不被计数器引用的都要被回收。(暂时不被使用的,没有引用的那个被自动回收保留的那个一个回收掉),附件为强制回收类。

         7.  编写代码注意:

         1)  无用的对象,没有引用

         2)  降低类设计之间的耦合度,注意对象传递引用的设计等

         3)  单例模式,在合适的时候使用

         4)  事件循环嵌套造成多次执行,或事件触发循环bug。

         5)  对象重复加同样的监听

        (4)AS3开发需要注意的地方:

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

(5)内存泄露举例:          1. 引用泄露:对子对象的引用,外部对本对象或子对象的引用都需要置null;          2. 系统类泄露:使用了系统类而忘记做删除操作了,如BindingUtils.bindSetter(),ChangeWatcher.watch()函数时候完毕后需要调用ChangeWatcher.unwatch()函数来清除引用 ,否则使用此函数的对象将不会被删除; 类似的还有MUSIC,VIDEO,IMAGE,TIMER,EVENT,BINDING等。         3. 效果泄露:当对组件应用效果Effect的时候,当本对象本删除时需要把本对象和子对象上的Effect动画停止掉,然后把Effect的target对象置null; 如果不停止掉动画直接把 Effect置null将不能正常移除对象。        4. SWF泄露:要完全删除一个SWF要调用它的unload()方法并且把对象置null;        5. 图片泄露:当Image对象使用完毕后要把source置null;(为测试);        6. 声音、视频泄露: 当不需要一个音乐或视频是需要停止音乐,删除对象,引用置null;

附件为强制回收类。调用方法:

import MyGc; MyGc.GC()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python的垃圾回收机制(引用计数+标

    我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念。在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就...

    py3study
  • Python学习笔记6——动态类型

    参考博客:Python进阶09 动态类型 Python深入06 Python的内存管理 都是非常棒的文章

    py3study
  • Python-变量对象引用

    记住:每一个对象都有两个东西,对象类型和引用的计数器 这连个东西决定了是否自动回收。 对象的垃圾回收:每个对象保持了一个引用计数器,计数器记录了当前指向该对象...

    py3study
  • Java强引用、软引用、弱引用及虚引用深入探讨

    引用类型在日常开发中并不常关注,也很少注意到,因此很多人忽略了它们的存在,而事实上,引用类型在Java体系中扮演着十分重要的角色,要想对Java体系有一个更深层...

    弗兰克的猫
  • 垃圾回收器如何处理循环引用

    垃圾回收是一门编程语言中必不可少的一部分,不论是手动释放内存的C和C++,还是自动回收垃圾的Java和C#等语言。对于Java这样的语言,一般的开发者不强求关心...

    技术小黑屋
  • 什么样的对象需要被 GC ?

    上一篇文章 JVM 基本介绍 我们了解了一些基本的 JVM 知识,本篇开始逐步学习垃圾回收,我们都知道既然叫垃圾回收,那回收的就应该是垃圾,可是我们怎么知道哪些...

    周三不加班
  • JVM&GC之java引用

    Java中的引用有点像C++中的指针,通过引用可以对堆中的对象进行操作。在Java程序中最常见的引用类型是强引用,也是默认的引用类型。当在Java语言中使用Ne...

    一觉睡到小时候
  • JVM中对象的回收过程

      当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配对应的内存空间,显然我的...

    用户4919348
  • JVM学习记录-对象已死吗

    前言 先来回顾一下,在jvm运行时数据区,分为两部分,一个部分是线程共享区,主要包括堆和方法区,另一部是线程私有区分包括本地方法栈,虚拟机栈和程序计数器。在线程...

    纪莫
  • Java 的强引用、弱引用、软引用、虚引用

            强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。如下:

    爱撸猫的杰

扫码关注云+社区

领取腾讯云代金券