java和flash的垃圾回收都是一个比较热门的话题,今天我也用一个例子来测试下flash的强制垃圾回收。主要用到的而一个类是LocalConnection。

在Flash player的debug版本中提供了gc的方法

Flash Player初始化运行时,会向操作系统申请一大块内存,如果程序很小,有可能根本用不了这么多内存,但FP在开始时不考虑这些,大多数情况下,第一次申请的内存总是不够用的。第一次申请的内存大小,与操作系统、浏览器环境有关。

当Flash Player发现已经申请的内存不够用时,它会再向操作系统申请一大块内存。但在申请之前,请注意,FP会尝试进行垃圾内存回收。那么它是如何回收的呢?
    Flash Player在内部使用懒惰式引用计数回收方案进行垃圾内存回收。

懒惰式指:FP并不会一次把所有可以回收的对象全部回收,它一次仅会回收一部分,如果内存不够用,它会向操作系统申请,如果系统无内存了,它会再次回收,如果全部回收了仍不够用,Game Over!

引用计数指:FP在内部给每个对象标记一个记号,当没有任何对象引用此对象时,它即是可以被回收的;如果一个容器内有许多相互关联的对象,当把这个容器从显示列表中移除,并且置为null后,它也是可以被回收的。

在清楚了FP的内部垃圾回收机制之后,我们可以创建两次没用的LocalConnection,并且连接并不存在的地址,故意抛出异常然后捕获,就强制垃
圾回收,因为,在AS3中LocalConnection是比较占用内存的对象,两次创建该类对象并尝试进行连接的内存开销大小足以请Flash
Player重新向操作系统申请内存,而在申请之前,FP会尝试回收。原理即是这么简单,非独使用LocalConnection可以,其它较耗内存的对
象也可以。

下面是我写的测试代码,主要测试三中情况下内存的使用情况。

  1. package
  2. {
  3. import flash.display.Sprite;
  4. import flash.external.ExternalInterface;
  5. import flash.net.LocalConnection;
  6. public class MemeryGcTest extends Sprite
  7. {
  8. private const num:int = 30000; //子元素个数  根据自己的电脑配置来设置
  9. private var parentContainer:Sprite;//父容器
  10. private var childrenRect:Array;//所有子元素的引用
  11. public function MemeryGcTest(){
  12. init();
  13. }
  14. private function init() : void{
  15. parentContainer=new Sprite();
  16. addChild(parentContainer);
  17. createAllChildrens();
  18. removeAllchildrens();
  19. setChildrenNull();
  20. //doGc();
  21. }
  22. /**
  23. * 移除所有对象
  24. *
  25. */
  26. private function removeAllchildrens():void {
  27. removeAllChildrens( );
  28. removeChild(parentContainer);
  29. }
  30. /**
  31. * 设置不用对象为null 否则不会进行垃圾回收
  32. *
  33. */
  34. private function setChildrenNull():void{
  35. childrenRect = null;
  36. parentContainer = null;
  37. }
  38. /**
  39. * 创建所有子元素
  40. *
  41. */
  42. private function createAllChildrens() : void {
  43. childrenRect=new Array();
  44. for(var i:int = 0;i<num; i++){
  45. var sprite:Sprite=new Sprite();
  46. childrenRect.push(sprite);
  47. sprite.graphics.beginFill(0xff0000);
  48. sprite.graphics.drawRect(0+i/50,0,100,100);
  49. sprite.graphics.endFill();
  50. parentContainer.addChild(sprite);
  51. }
  52. }
  53. /**
  54. * 移除所有子元素
  55. *
  56. */
  57. private function removeAllChildrens():void{
  58. for(var i:int=0;i<num;i++){
  59. parentContainer.removeChild(childrenRect[i]);
  60. delete childrenRect[i];
  61. }
  62. }
  63. /**
  64. * 强制垃圾回收
  65. *
  66. */
  67. private function doGc():void{
  68. try{
  69. var conn1:LocalConnection= new LocalConnection();
  70. conn1.connect("testGc");
  71. var conn2:LocalConnection= new LocalConnection();
  72. conn2.connect("testGc");
  73. }catch(error:Error){
  74. conn1 = null;
  75. conn2 = null;
  76. }
  77. }
  78. }
  79. }

第一种情况,不设置不用元素为null和强制垃圾回收

  1. private function init() : void{
  2. parentContainer=new Sprite();
  3. addChild(parentContainer);
  4. createAllChildrens();
  5. removeAllchildrens();
  6. //setChildrenNull();
  7. //doGc();

测试结果如下:

可以看出占用的内存比较高,点击GC按钮内存依然是“居高不下”。

第二种情况,设置不用元素为null但不强制执行垃圾回收。

  1. private function init() : void{
  2. parentContainer=new Sprite();
  3. addChild(parentContainer);
  4. createAllChildrens();
  5. removeAllchildrens();
  6. setChildrenNull();
  7. //doGc();

测试结果如下:

设置null后虽然刚开始峰值很高,但是Flash Player执行了垃圾回收,很快内存下降到12K。

第三种情况,设置不用对象为null并强制进行垃圾回收。

  1. private function init() : void{
  2. parentContainer=new Sprite();
  3. addChild(parentContainer);
  4. createAllChildrens();
  5. removeAllchildrens();
  6. setChildrenNull();
  7. doGc();

测试结果如下:

可以看出强制垃圾回收确实执行了。

内存泄露举例:
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。

内存泄露解决方法:
1.
在组件的REMOVED_FROM_STAGE事件回掉中做垃圾处理操作(移除所有对外引用(不管是VO还是组件的都需要删除),删除监听器,调用系统类
的清除方法) 先remove再置null, 确保被remove或者removeAll后的对象在外部的引用全部释放干净。
2. 利用Flex的性能优化工具Profile来对项目进程进行监控,可知道历史创建过哪些对象,目前有哪些对象没有被删除,创建的数量,占用的内存比例和用量,创建过程等信息。

总结:关键还是要做好清除工作,自己设置的引用自己要记得删除,自己用过的系统类要记得做好回收处理工作。 以上问题解决的好的话不需要自定义强制回收器也有可能被系统正常的自动回收掉。

flex 强制垃圾回收的更多相关文章

  1. C#或者.NET下的强制垃圾回收办法

    转载 2011年03月16日 17:21:00 标签: c# / .net / button / object / stream / class 8185 今天来谈谈C#的GC,也就是垃圾回收机制,非 ...

  2. 【C# .Net GC】强制垃圾回收 和System GC

    属性 GC.MaxGeneration:获取系统当前支持的最大代数. 方法 GC.GetTotalMemory(bool forceFullCollection) 方法  true表示该方法先做垃圾收 ...

  3. as3中强制垃圾回收

    private function doClearance():void { // trace("clear"); try{ new LocalConnection().connec ...

  4. flex 垃圾回收

    原文在这里:Garbage Collection with Flex and Adobe Air 我终于有时间来整理在flexcamp上演讲的东西并写篇博客了.就在flexcamp前一个月,我几乎天天 ...

  5. Java的垃圾回收机制:强制回收System.gc() Runtime.getTime().gc()

    垃圾回收 当引用类型的实体,如对象.数组等不再被任何变量引用的时候.这块占用的内存就成为了垃圾.JVM会根据自己的策略决定是回收内存 注意: 垃圾回收只回收内存中的对象,无法回收物理资源(数据库连接, ...

  6. .NET垃圾回收 – 原理浅析

    在开发.NET程序过程中,由于CLR中的垃圾回收(garbage collection)机制会管理已分配的对象,所以程序员就可以不用关注对象什么时候释放内存空间了.但是,了解垃圾回收机制还是很有必要的 ...

  7. .NET垃圾回收:非托管资源,IDispose和析构函数的结合

    http://blog.jobbole.com/85436/ 原文出处: 田小计划   欢迎分享原创到伯乐头条 前面一篇文章介绍了垃圾回收的基本工作原理,垃圾回收器并不是可以管理内存中的所有资源.对于 ...

  8. c# -- 对象销毁和垃圾回收

    有些对象需要显示地销毁代码来释放资源,比如打开的文件资源,锁,操作系统句柄和非托管对象.在.NET中,这就是所谓的对象销毁,它通过IDisposal接口来实现.不再使用的对象所占用的内存管理,必须在某 ...

  9. java 之 对象与垃圾回收

    1.垃圾回收机制只负责回收堆内存中的对象,不会回收任何物理资源(如数据库连接,网络IO等资源) 2.程序无法精确控制垃圾回收的运行,垃圾回收会在合适的时候运行.当对象永久的失去引用后,系统会在合适的时 ...

随机推荐

  1. java代码转化为jar包,再转化为.exe文件步骤

    下面是具体步骤: 一.先把自己的程序发布成jar文件 这是eclipse自带的功能,右键工程包-->Export 然后选择Java-->JAR file,next 选择输出路径,next ...

  2. MySQL 的自增 ID 用完了,怎么办?

      一.简述 在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加.在 MySQL 中只要定义了这个数的字节长度,那么就会 ...

  3. POJ 3414 Pots (BFS/DFS)

    Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7783   Accepted: 3261   Special Ju ...

  4. Client does not support authentication protocol requested by server; consider upgrading MySQL client

    出现错误 Client does not support authentication protocol requested by server; consider upgrading MySQL c ...

  5. es7.2版本安装ik分词

    (一)到官网下载https://github.com/medcl/elasticsearch-analysis-ik对应版本的ik(直接下载releases版本,避免maven打包!!!如果不是这个版 ...

  6. 在XCode中使用XCTest

    测试驱动开发并不是一个很新鲜的概念了.在我最开始学习程序编写时,最喜欢干的事情就是编写一段代码,然后运行观察结果是否正确.我所学习第一门语言是c语言,用的最多的是在算法设计上,那时候最常做的事情就是编 ...

  7. django基础篇02-url路由系统

    django的路由系统: 一.基本用法: 1.path('index', views.index), # 通过类的方式创建url映射 2.path('home', views.Home.as_view ...

  8. Linux学习--第一天--Unix 、 Linux 发展史,Linux应用领域

    UNIX发展史 肯·汤姆森开发出linux. 肯·汤姆森的同事丹尼斯·里奇在1971年开发了C语言. 操作系统 公司 硬件平台 AIX IBM PowerPC HP-UX HP PA-RISC Sol ...

  9. JavaScript设计模式样例四 —— 单例模式

    单例模式(Singleton Pattern): 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 目的:阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例. 场景: ...

  10. layui下拉框右边图标动画,不要动画

    /* 取消动画 / .layui-form-selected .layui-edge { margin-top: -3px; -webkit-transform: rotate(0deg); tran ...