flex 强制垃圾回收

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

 

     在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能够,其它较耗内存的对 象也能够。测试

 

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

   

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

 

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

  

  

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

 

测试结果以下:spa

 

  

 

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

 

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

 

Java代码   收藏代码
  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并强制进行垃圾回收。

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

 

 

测试结果以下:

 

  

 

 

能够看出强制垃圾回收确实执行了。

 

 

 

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


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

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

相关文章
相关标签/搜索