【问题标题】:ExternalInterface.call leaks in IE 9IE 9 中的 ExternalInterface.call 泄漏
【发布时间】:2013-09-24 19:41:58
【问题描述】:

我创建了一个非常简单的 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。不好。

有人见过这个吗?我找不到与此相关的任何其他帖子。

【问题讨论】:

  • 不错!最后会崩溃吗?
  • 如果你让它运行足够长的时间是的。我们有客户抱怨 IE 崩溃,我们将其范围缩小到这个问题。
  • 如果您不使用ExternalInterface.call()(在您的输入帧处理程序中),IE 内存中的一切都好吗?您还可以指定您在哪个版本的 IE、Flash 和 Windows 操作系统中看到此问题。最后,我会尝试调低一些(进入帧事件经常发生)。如果您将ExternalInterface.call() 与触发的Timer 一起使用会发生什么情况,比如每10 秒一次。我猜这个问题只是发生得更慢......
  • 尝试每 10 秒触发一次,而不是使用 setInterval 并仍然得到泄漏。它每 10 秒上升约 6k。
  • 其实并没有那么一致。有时它会跳大约 80k,然后在一分钟后恢复到原来的水平。然而,随着时间的推移,它似乎确实增加了。不过很难说,因为它太慢了。我让它运行一段时间,看看会发生什么。

标签: flash internet-explorer memory-leaks externalinterface


【解决方案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;
        }
    }
}

所以,你只需要使用 ExternalInterfaceExtended 类而不是常规的 ExternalInterface。

【讨论】:

猜你喜欢
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多