5

デモ用に非常に単純な SWF を作成しました。

package {
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.external.ExternalInterface;

    public class FlashIELeak extends MovieClip {

        public function FlashIELeak() {
            addEventListener(Event.ENTER_FRAME, onFrame);
        }

        private function onFrame(e:Event):void {
            ExternalInterface.call("test", null);
        }
    }
}

それをChromeにロードしてください。問題ありません。メモリは多かれ少なかれ固定されたままです。

それをIEにロードすると、メモリがどんどん増え続けます-約30k / s。テスト関数を宣言する必要さえありません。ページに swf を埋め込むだけで、リークが発生します。私たちのプロジェクトでは、いくつかのプロパティを持つオブジェクトを渡していますが、IE は 120k/s のようにリークしています。良くない。

これを前に見た人はいますか?これに関連する他の投稿を見つけることができませんでした。

4

1 に答える 1

1

約2年前に有名なロシアのブログに投稿がありました. Alexander Kozlovskij (別名 Fizzer) がこの問題を説明しました。彼が作成した回避策は次のとおりです。

package ru.kozlovskij.external
{
    import flash.external.ExternalInterface;
    /**
     * @author a.kozlovskij
     * @copy flash.external.ExternalInterface
     */
    public final class ExternalInterfaceExtended
    {
        private static const instance :ExternalInterfaceExtended= new ExternalInterfaceExtended();
        private static var methodName :String;

        /**
         * U can't instanciate this class, because it implements a Singletone pattern.
         * @copy flash.external.ExternalInterface.ExternalInterface()
         */
        public function ExternalInterfaceExtended()
        {
            instance && new ExternalInterface();
            methodName = '__flash__addCallback_' + ExternalInterface.objectID;
        }

        private static function updateJS():void
        {
            const jsFunc :String = 'function(){ ' +
                methodName + ' = __flash__addCallback = function(flashObj, methodName)' +
                '{' +
                '    alert("JS: called overridden __flash__addCallback(" + arguments[0] + ", " + arguments[1] + ")");' +
                '    flashObj[methodName] = ' +
                '     (function(methodName)' +
                '     {' +
                '     return function()' +
                '     {' +
                '     this.CallFunction(\'\' + __flash__argumentsToXML(arguments,  + \'\');' +
                '     };' + //dangling semi-colon for IE 6
                '     })(methodName);' + //force re-closure to prevent IE memory leaks
                '};' +
                '}';

            ExternalInterface.call(jsFunc);
        }

        /**
         * Fixed: Mem leaks in native addCallback-js-closure.
         * @copy flash.external.ExternalInterface.addCallback()
         */
        public static function addCallback(functionName :String, closure :Function):void
        {
            updateJS();
            ExternalInterface.addCallback(functionName, closure);
            //ExternalInterface.call(methodName, functionName);
            //ExternalInterface.call('__flash__addCallback_ext', null, functionName);
        }

        /**
         * @copy flash.external.ExternalInterface.call()
         */
        public static function call(functionName :String, ...parameters :Array):*
        {
            parameters.unshift(functionName);
            return ExternalInterface.call.apply(ExternalInterfaceExtended, parameters);
        }

        /**
         * @copy flash.external.ExternalInterface.available
         */
        public static function get available():Boolean
        {
            return ExternalInterface.available;
        }

        /**
         * @copy flash.external.ExternalInterface.objectID
         */
        public static function get objectID():String
        {
            return ExternalInterface.objectID;
        }

        /**
         * @copy flash.external.ExternalInterface.marshallExceptions
         */
        public static function get marshallExceptions():Boolean
        {
            return ExternalInterface.marshallExceptions;
        }

        public static function set marshallExceptions(value :Boolean):void
        {
            ExternalInterface.marshallExceptions = value;
        }
    }
}

したがって、通常の ExternalInterface の代わりに ExternalInterfaceExtended クラスを使用するだけで済みます。

于 2013-12-02T13:45:09.923 に答える