ガベージコレクションは、メモリに余裕があるとなかなか発動されません。[ムービープレビュー]などのデバッグ環境と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■クリックでガベージコレクションが働いてメモリ使用は減る
なお、一般のネット環境でも動くことを確かめるため、wonderflにサンプルをアップロードしました。初めに述べたように正規サポートの機能ではありませんので、テストや実験などの範囲で使うのがよいでしょう。
Garbage Collection Hack - wonderfl build flash online
[*1] nick bilyk「flash garbage collection」の「Forcing the garbage collector to run」参照。