Actionscript 3 已完成、未引用计时器的垃圾收集
我有一个计时器,比如:Actionscript 3 已完成、未引用计时器的垃圾收集,actionscript-3,timer,garbage-collection,Actionscript 3,Timer,Garbage Collection,我有一个计时器,比如: private var timer:Timer; public function doThingLater():void { timer = new Timer(1000, 1); var someBigThing:SomeBigThing = new SomeBigThing(); timer.addEventListener(TimerEvent.TIMER_COMPLETE, function():void { some
private var timer:Timer;
public function doThingLater():void {
timer = new Timer(1000, 1);
var someBigThing:SomeBigThing = new SomeBigThing();
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
someBigThing.doThing();
timer = null;
});
timer.start();
}
我需要确定有什么东西是垃圾收集的
我的谷歌搜索结果一直告诉我,如果计时器从未停止,它将永远不会被收集,但那些停止的计时器呢
我相当肯定,仅仅将字段设置为null并不一定允许收集;如果我有这个:
public function doThingLater():void {
//initialize timer...
timer.start();
timer = null;
}
我仍然希望计时器运行
我知道可以通过在计时器上调用removeEventListener来确保它被收集,但是侦听器是匿名的;显然我可以做到这一点,但我认为匿名侦听器更具可读性。对,所以我做了一些实验,看看能找到什么,我的代码如下。我对这些都不是100%肯定,但我的主要发现是:
- 是的,停止的计时器最终将被收集
- 删除侦听器也同样有效
- 使用弱引用的监听器也可以,只要对监听器的另一个引用保持到不再需要为止
- 垃圾收集何时起作用很难预测,即使是使用
System.gc()
- 匿名函数复制当前函数的整个激活记录,这导致了另外两个令人不安的结论:
- 匿名函数可能包含对对象的意外引用,因此从
阻止function foo():Function { var thing:Object; //initialize thing //Do a bunch of other stuff. return function():void { /*do nothing*/ }; }
对象被垃圾收集
- 匿名函数引用原始局部变量,因此
如果使用了var thing:SomeClass; var function:Function = function():void { thing.doAThing(); }; //do some stuff thing = null;
,将导致空引用错误函数
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.system.System;
import flash.utils.Dictionary;
import flash.utils.Timer;
public class Main extends Sprite
{
public static var objects:Dictionary;
private var control:Vector.<int>;
private var doesNotStop:Timer;
private var stops:Timer;
private var removesListener:Timer;
private var usesWeakListener:Timer;
private static var before:Timer, after:Timer;
private static var beforeTime:Number = 100;
private static var time:Number = 1000;
private static var afterTime:Number = 2000;
private static var wellAfterTime:Number = 6000;
public function Main():void
{
if (stage) init(null);
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(event:Event):void {
doIt();
printObjects("After releasing references, ");
stage.addEventListener(KeyboardEvent.KEY_DOWN, test);
}
public function test(event:Event):void {
printObjects("On key press, ");
}
public function doIt():void {
objects = new Dictionary(true);
//Create objects.
var thing:Vector.<int> = createBigObject();
control = createBigObject();
var stopsObject:Object = initializeStops();
var doesNotStopObject:Object = initializeDoesNotStop();
var removesListenerObject:Object = initializeRemovesListener();
var usesWeakListenerObject:Object = initializeUsesWeakListener();
//Add them to the dictionary.
objects[control] = "control";
objects[thing] = "thing";
objects[doesNotStop] = "does not stop";
objects[doesNotStopObject] = "does not stop object";
objects[stops] = "stops";
objects[stopsObject] = "stops object";
objects[removesListener] = "removes listener";
objects[removesListenerObject] = "removes listener object";
objects[usesWeakListener] = "uses weak listener";
objects[usesWeakListenerObject] = "uses weak listener object";
printObjects("Before releasing references, ");
//Release local references.
control = null;
doesNotStop = null;
doesNotStopObject = null;
stops = null;
stopsObject = null;
removesListener = null;
removesListenerObject = null;
usesWeakListener = null;
usesWeakListenerObject = null;
//Start timers to check gc later.
before = new Timer(beforeTime, 1);
var listener:Function = function():void {
printObjects("Before the Timer has finished, ");
};
before.addEventListener(TimerEvent.TIMER_COMPLETE, listener, false, 0, false);
before.start();
after = new Timer(afterTime, 1);
after.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
printObjects("After the Timer has finished, ");
});
after.start();
var wellAfter:Timer = new Timer(wellAfterTime, 1);
wellAfter.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
printObjects("Well after the Timer has finished, ");
});
wellAfter.start();
}
private function initializeDoesNotStop():Object {
var object:Vector.<int> = createBigObject();
doesNotStop = new Timer(time, 0);
doesNotStop.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
object[0] = 10;
});
doesNotStop.start();
return object;
}
private function initializeStops():Object {
var object:Vector.<int> = createBigObject();
stops = new Timer(time, 1);
stops.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
object[0] = 10;
});
stops.start();
return object;
}
private function initializeRemovesListener():Object {
var object:Vector.<int> = createBigObject();
var listener:Function = function(event:Event):void {
object[0] = 10;
(event.target as Timer).removeEventListener(TimerEvent.TIMER_COMPLETE, listener);
};
removesListener = new Timer(time, 1);
removesListener.addEventListener(TimerEvent.TIMER_COMPLETE, listener);
removesListener.start();
return object;
}
private function initializeUsesWeakListener():Object {
var object:Vector.<int> = createBigObject();
usesWeakListener = new Timer(time, 1);
usesWeakListener.addEventListener(TimerEvent.TIMER_COMPLETE, function():void {
object[0] = 10;
}, false, 0, true);
usesWeakListener.start();
return object;
}
public static function createBigObject():Vector.<int> {
var out:Vector.<int> = new Vector.<int>(100, true);
for (var i:int = 0; i < 100; i++)
out[i] = i;
return out;
}
public static function printObjects(msg:String):void {
System.gc();
var output:String = msg + "the following objects have not been collected: ";
var objectNames:Vector.<String> = new Vector.<String>();
for each (var value:String in objects) {
objectNames.push(value);
}
objectNames.sort(0);
for each (var str:String in objectNames) {
output += str + ", ";
}
trace(output);
}
}
}
包
{
导入flash.display.Sprite;
导入flash.events.Event;
导入flash.events.KeyboardEvent;
导入flash.events.TimerEvent;
导入flash.system.system;
导入flash.utils.Dictionary;
导入flash.utils.Timer;
公共类Main扩展了Sprite
{
公共静态var对象:字典;
私有var控制:向量。;
私有变量不停止:计时器;
私有变量停止:定时器;
私有var removesListener:计时器;
私有变量useSwakListener:计时器;
私有静态变量before:Timer,after:Timer;
私有静态变量beforeTime:Number=100;
私有静态变量时间:Number=1000;
私有静态变量后时间:Number=2000;
私有静态var WellAfterime:Number=6000;
公共函数Main():void
{
if(stage)init(null);
其他的
addEventListener(Event.ADDED_TO_STAGE,init);
}
公共函数初始化(事件:事件):无效{
doIt();
printObjects(“发布引用后,”);
stage.addEventListener(KeyboardEvent.KEY_DOWN,test);
}
公共功能测试(事件:事件):无效{
printObjects(“按键时,”);
}
公共函数doIt():void{
objects=新字典(true);
//创建对象。
变量thing:Vector.=createBigObject();
control=createBigObject();
var stopsObject:Object=initializeStops();
var doesnotstobject:Object=initializedesnotstop();
var removesListenerObject:Object=initializeRemovesListener();
var useSwakListenerObject:Object=InitializeUserWeakListener();
//将它们添加到字典中。
对象[控制]=“控制”;
对象[事物]=“事物”;
对象[doesNotStop]=“不停止”;
对象[doesNotStopObject]=“不停止对象”;
对象[停止]=“停止”;
对象[停止对象]=“停止对象”;
对象[removesListener]=“删除侦听器”;
对象[RemoveListenerObject]=“删除侦听器对象”;
对象[UseSwakListener]=“使用弱侦听器”;
对象[UseSwakListenerObject]=“使用弱侦听器对象”;
printObjects(“在发布引用之前,”);
//发布本地引用。
控制=空;
doesNotStop=null;
doesNotStopObject=null;
停止=空;
stopsObject=null;
removesListener=null;
RemoveListenerObject=null;
UseSwakListener=null;
UseSwakListenerObject=null;
//启动计时器以稍后检查gc。
before=新计时器(beforeTime,1);
变量侦听器:Function=Function():void{
printObjects(“在计时器完成之前,”);
};
before.addEventListener(TimerEvent.TIMER\u COMPLETE,listener,false,0,false);
before.start();
after=新计时器(after Time,1);
在.addEventListener(TimerEvent.TIMER_完成后,函数():void{
printObjects(“计时器完成后,”);
});
在.start()之后;
var wellAfter:计时器=新计时器(wellAfterTime,1);
wellAfter.addEventListener(TimerEvent.TIMER_完成,函数():void{
printObjects(“在计时器完成之后,”);
});
wellAfter.start();
}
私有函数initializedesnotstop():对象{
变量对象:Vector.=createBigObject();
doesNotStop=新计时器(时间,0);
doesNotStop.addEventListener(TimerEvent.TIMER_完成,函数():void{
对象[0]=10;
});
doesNotStop.start();
返回对象;
}
私有函数initializeStops():对象{