转:http://www.cnblogs.com/janyou/archive/2008/11/25/1340753.html
http://tech.ccidnet.com/art/3539/20100810/2148307_1.html
从目前情况看,Flex 3(AS3)存在严重的memoy leak(内存泄露)问题,这些问题中一部分可以合适的编码方式来避免,还有一些问题目前只有等待Flex SDK更新了。
感觉Flex 的商业应用目前只能在初级阶段。列举一些产生memoy leak的情景。
(1)EventListeners
监听系统级别对象导致内存泄露:
override protected function mouseDownHandler(e:Event):void
{
systemManager.addEventListener(“mouseUp”,mouseUpHandler);
}
解决办法:
Ø 在dispose的时候移除监听:
systemManager.removeEventListener(“mouseUp”, mouseUpHandler);
Ø 使用弱引用:
override protected function mouseDownHandler(e:Event):void
{
systemManager.addEventListener(“mouseUp”,mouseUpHandler, false, 0, true);
}
以下方式事件监听不会导致内存泄露
Ø 弱引用
someObject.addEventListener(MouseClick.CLICK, handlerFunction,false, 0, true);
Ø 自身引用
this.addEventListener(MouseClick.CLICK, handlerFunction);
Ø 子对象引用
private var childObject:UIComponent = new UIComponent;
addChild(childObject);
childObject.addEventListener(MouseEvent.CLICK, clickHandler);
(2)static members
Class (或MXML)中有:
public static var _eventService : MyService=newMyService();
在dispose时,需要设置:
_eventService =null;
(3)module(未解决)
moduleLoader unloadModule后,ModuleInfo 并不会被GC.
Garbage Collectionin a MultiCore Modular Pipes Application
这篇文章介绍了一种GC策略,感觉对于ModuleInfo 的GC无效。(我打不开)
(4)CSSStyle
module 中如果使用了shell的CSS定义或是<mx:Style> (现在应该是<fx:Style>,这块我没有测试过)这样的定义,那么这个module将不能GC.
弹出的窗口应该是同样的结果.
解决方法,使用动态CSS文件
module init中
StyleManager.loadStyleDeclarations("css/myStyle.swf");
module dispose中
StyleManager.unloadStyleDeclarations("css/myStyle.swf");
(5)TextInput/Textarea(未解决)
如果module中有window使用了TextInput/Textarea控件,不点击没有问题,只要点上去,那么很遗憾了,module和所在窗体将不能被GC.这个BUG非常严重,目前还没有解决方法。
memory leak whenusing TextInput and TextArea when click the keyboard
这里面附加的解决方法无效。
通过profiler分析,应该和Focusmanager有关,只有一点击就不会释放。
(6)CursorManager.setCursor
使用了
cursorID = CursorManager.setCursor(iconClosed);
dispose时要
CursorManager.removeCursor(cursorID);
(7)Bitmap
如果使用Bitmap,结束时需要调用其dispose方法,否则内存消耗巨大。
var bmp:Bitmap =new Bitmap();
if (bmp.bitmapData!=null) {
bmp.bitmapData.dispose();
}
(8)Image
包含了Image对象时,在removeChildren时会造成不能释放(测试多次,结果不一,建议还是做如下处理)。
解决:
img.source = null;
this.removeChild(img);
img = null;
(9)Effect
当对组件应用效果Effect的时候,当本对象本删除时需要把本对象和子对象上的Effect动画停止掉,然后把Effect的target对象置null;如果不停止掉动画直接把Effect置null将不能正常移除对象。(我自己测试发现,Effect的duration="0"也会导致内存泄露,设置大于0就不会了。)
(10)SWF泄露
要完全删除一个SWF要调用它的unload()方法并且把对象置null;
(11)Timer
只要Timer一直在运行,就算程序不再引用,FLEX内存的内存回收机制也不会回收Timer及其相关类/变量的资源而且一直在运行。
解决方案:在dispose的时候:
if(timer)
{
timer.stop();
timer= null;
}
(12)声音、视频泄露
当不需要一个音乐或视频是需要停止音乐,删除对象,引用置null;
总结:Flex内存泄露解决方法:
Ø 在组件的REMOVED_FROM_STAGE事件中做垃圾处理操作(移除所有对外引用(不管是VO还是组件的都需要删除),删除监听器,调用系统类的清除方法)
Ø 先remove再置null,确保被remove或者removeAll后的对象在外部的引用全部释放干净;
Ø 利用Flex的性能优化工具Profile来对项目进程进行监控,可知道历史创建过哪些对象,目前有哪些对象没有被删除,创建的数量,占用的内存比例和用量,创建过程等信息;