[AS3] ガベージコレクションを働かせる裏技 [Edit]

ガベージコレクションは、メモリに余裕があるとなかなか発動されません。[ムービープレビュー]などのデバッグ環境とAIRであればSystem.gc()メソッドが使えます。でも、一般のネット環境ではこのメソッドは使えません。そこで、正規サポートはされてはいない裏技をひとつご紹介します。

ドキュメント化されていないFlash Playerのふるまいとして、LocalConnection.connect()メソッドを2回呼出すとガベージコレクションが働くようです[*1]。たとえば、つぎのフレームアクション(スクリプト001)を書いて、[ムービープレビュー]でステージをマウスクリックすればガベージコレクションにより[出力]が止まります。

スクリプト001■ガベージコレクションを働かせる
var nCount:uint = 0;
var mySprite:Sprite = new Sprite();
var myTimer:Timer = new Timer(500, 1)
stage.addEventListener(MouseEvent.CLICK, xStop);
mySprite.addEventListener(Event.ENTER_FRAME, test);
mySprite = null;
myTimer.addEventListener(TimerEvent.TIMER, xGetMemory);
function test(eventObject:Event):void {
	trace(nCount++, System.totalMemory);
}
function xStop(eventObject:MouseEvent):void {
	gcHack();
	myTimer.start();
}
function gcHack():void {
	// [ムービープレビュー]なら以下でも動作する
	// System.gc();
	try {	// ガベージコレクションの裏技
		new LocalConnection().connect("test");
		new LocalConnection().connect("test");
	} catch (errorObject:Error) {}
}
function xGetMemory(eventObject:TimerEvent):void {
	trace(eventObject.type, System.totalMemory);
}

ステージをクリックすると、StageオブジェクトのInteractiveObject.clickイベントに加えたリスナー関数(xStop())が裏技の処理(gcHack())を呼出してガベージコレクトします。その結果、Spriteインスタンス(mySprite)のDisplayObject.enterFrameイベントリスナー(test())がメモリから消えて[出力]は止まります。併せて、TimerオブジェクトのTimer.timerイベントリスナーが0.5秒後のメモリ使用量を確かめています(図001)。

図001■クリックでガベージコレクションが働いてメモリ使用は減る
FF1107311_001.gif

なお、一般のネット環境でも動くことを確かめるため、wonderflにサンプルをアップロードしました。初めに述べたように正規サポートの機能ではありませんので、テストや実験などの範囲で使うのがよいでしょう。

Garbage Collection Hack - wonderfl build flash online


[*1] nick bilyk「flash garbage collection」の「Forcing the garbage collector to run」参照。

コメント

この記事にコメントを書く

記事に対するテクニカルな質問はご遠慮ください(利用規約)。

その他の記事