1.不知道什么时候才会出现的GC
2.内存泄露
个人认为,flashPlayer内存占用高很大程度上不是因为无法手动GC,而是因为设计上的失误(是天真地以为flash/flex像C#/java 那样有防止内存泄露的完善的机制)而导致无穷无尽的内存占用。如果你经常被这些问题困扰,那么你有幸了,因为你遇到了猫粮,遇到了能帮你把应用内存占用降 下来的文章。
测试环境的建立
为了测试环境的纯净,在数据输出方面我只使用了Trace。
下面是MemoryMonitor的代码:(可怜徐灿的代码被我整容了...大概只保留了定时器还有CallBackFunction)
这个东西主要用于每隔一秒就检测一次内存,并且执行一次callBackFunction。
复制内容到剪贴板代码:
<?xml version="1.0" encoding="UTF-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="start()">
<mx:Script>
<![CDATA[
import flash.utils.getTimer;
private var timer:Timer;
public var interval:int = 1000;
public var callbackFunction:Function = null;
private function timerHandler(event:TimerEvent):void
{
trace("Time:"+getTimer()+"cur:"+System.totalMemory)
if (callbackFunction != null)
callbackFunction();
}
public function start():void
{
timer = new Timer(interval);
timer.addEventListener("timer", timerHandler);
timer.start();
}
public function stop():void
{
timer.stop();
timer.removeEventListener("timer", timerHandler);
timer = null;
}
]]>
</mx:Script>
</mx:Canvas>
主程序代码
这个就是上面提到的两贴代码的宿主了。我们只需要更改enterFrameHandler这个函数就能对数据进行测试。
徐灿的原版代码将在最后奉上.....
复制内容到剪贴板代码:
<?xml version="1.0" encoding="UTF-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns:local="*">
<mx:Script>
<![CDATA[
import mx.controls.VideoDisplay;
private function enterFrameHandler():void
{
//TODO:测试内存占用的代码写在这里
}
]]>
</mx:Script>
<local:MemoryMonitor callbackFunction="enterFrameHandler" />
<mx:ViewStack id="abc" />
</mx:Application>
复制内容到剪贴板代码:
private function enterFrameHandler():void
{
var o:Object = new Object();
MyGC.GC();
}
复制内容到剪贴板代码:
private function enterFrameHandler():void
{
var o:Object = new Object();
o = null;
MyGC.GC();
}
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
MyGC.GC();
}
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
MyGC.GC();
}
只移除显示对象
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
this.removeChild(flvplay);
}
彻底清除引用的对比
没有设置null版
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
this.removeChild(flvplay);
MyGC.GC();
}
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
this.removeChild(flvplay);
flvplay = null;
MyGC.GC();
}
添加+移除+内存回收
这个最搞笑,越来越少越来越少......
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
this.removeEventListener(s,abc);
function abc(){}
MyGC.GC();
}
viewStack对比
上面的是Flex3 SDK的,下面的是Flex2 Hotfix3的SDK
徐灿说Flex2SDK的viewStack有bug,但是这样测试好像看不出什么问题..大家如果想深究的话就要自己测试一下
当然代码里面能发现问题,这些就不好说了..
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
abc.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
abc.removeChild(flvplay);
MyGC.GC();
}
总结
这次的测试就暂时到这里
我个人的感觉就是:
1.开了什么就要关掉什么
2.设置为null这一做法是没啥作用的,有没有被引用系统自己清楚,自己YY也没用
3.GC长做,特别是在清理的时候,这样能保证内存在第一时间被回收。
希望本文能对大家有点帮助
<!--①楼帖间广告开始-->
关于视频的,就是必须close了再new才能保证flv已经占的内存被释放……不然会造成内存泄露。
任何新addChild进来的东西关闭的时候都要removeChild掉。
还有就是FLEX 2 SDK里只要牵扯到ViewStack的组件都有先天性的内存泄露。这个问题在FLEX 3 SDK中得到了解决。
使用Module的要注意,不是只要unload了模块就等于把里面全部资源都释放了。必须把里面的东西手动清除。
比如我那个例子里面的,都removeAllChildren了。如果module里有正在动的东西或者什么的,他光unload那个module只是说 明把他从显示上去掉,里面的东西没有消除引用,所以必须unload的时候也把module里的东西removeAllChildren了