actionscript-3 - HTMLLoader/StageWebView 内存泄漏

标签 actionscript-3 air

创建 StageWebView 的实例时,如果您在多个站点之间切换,您会注意到使用的内存量缓慢增加。如果您正在查看 2/3 的站点,这不是问题,但在使用内置浏览器创建 AIR 应用程序时,我现在在内存管理方面遇到了瓶颈。

无论我做什么

  • 每次调用后 StageWebView.dispose()
  • 重置阶段

问题依然存在。每加载一个网页都会增加 3mb 的内存,逐渐增加到 1gb 以上并导致应用程序崩溃。

我在 StageWebView 实例上没有事件监听器。我绝对没有提到它。在加载第二个 URL 后,内存并没有完全重置。

这可以通过在 AIR 中运行以下命令看到:

package kazo
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    import mx.controls.Button;
    import mx.core.UIComponent;
    import flash.system.System;

    /**
     * ...
     * @author KM
     */
    public class Controller extends UIComponent
    {

        private var stageWeb:StageWebView;
        private var url:uint = 0;

        private const URL_ARRAY:Array = [
            'http://www.mmo-champion.com/',
            'http://www.bbc.co.uk/news/',
            'http://www.twitch.tv/riotgames/',
            'http://www.stackoverflow.com/'
        ]

        /**
         * 
         */
        public function Controller() 
        {
            addEventListener(Event.ADDED_TO_STAGE, init);
        }

        /**
         * 
         * @param   e
         */
        private function init(e:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            stageWeb = new StageWebView();
            stageWeb.stage = stage;
            stageWeb.viewPort = new Rectangle(0, 80, width, height - 50);

            var btn:Button = new Button();
            addChild(btn);
            btn.label = 'Load URL';
            btn.x = 0;
            btn.y = 10;;
            btn.width = 100;
            btn.height = 30;
            btn.addEventListener(MouseEvent.CLICK, load);

            btn = new Button();
            btn.label = 'Try to GC';
            btn.x = 150;
            btn.y = 10;;
            btn.width = 100;
            btn.height = 30;
            addChild(btn);
            btn.addEventListener(MouseEvent.CLICK, tryGC);

            /// 26,576k
        }

        /**
         * 
         * @param   e
         */
        private function load(e:MouseEvent):void {
            if (!stageWeb) {
                stageWeb = new StageWebView();
                stageWeb.stage = stage;
                stageWeb.viewPort = new Rectangle(0, 80, width, height - 50);
            }               

            stageWeb.loadURL(URL_ARRAY[url % 4]);

            url++;
        }

        /**
         * 
         * @param   e
         */
        private function tryGC(e:MouseEvent):void {
            stageWeb.stage = null;
            stageWeb.viewPort = null;
            stageWeb.dispose();
            stageWeb = null;
            System.gc();
        }

    }

}

有没有人有这方面的经验?

最佳答案

我对您的代码做了一些小改动,使其可以使用 AIR 14 SDK(ASC 2.0,无 flex)进行编译,我构建并测试了 air 应用程序

mxmlc -optimize=true +configname=air Controller.as && adl Controller.xml

并使用 Adob​​e Scout 观察内存使用情况

GC后内存稳定,稳定在14481kB

您可以将 -advanced-telemetry=true 选项添加到 mxmlc 以精确跟踪分配/取消分配,只需考虑按下“隐藏已清除对象”开关并选择两次 GC 之间的范围。你会看到一些对象没有立即释放,但你也会看到,如果你同时选择其中的几个范围,那些临时泄漏不会加起来,这解释了为什么在 GC 环境中内存不会不断增加, 内存泄漏并不是真正的内存泄漏

如何衡量内存使用情况?

我检查了 adl 进程的内存使用情况,它更高 (> 100MB) 并且不太稳定,但在 GC 之后仍然稳定在 110 到 120MB 之间。无论如何,它看起来绝对不会增加到 1 GB

请记住,ActionScript GC 是惰性的,并保留对象池以供将来重用,任何执行超过 hello world 的应用程序有时都会有奇怪的内存行为,这是 AVM2 工作方式的一部分。

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    import flash.system.System;
    import flash.text.TextField;

    /**
     * ...
     * @author KM
     */
    public class Controller extends Sprite
    {

        private var stageWeb:StageWebView;
        private var url:uint = 0;

        private const URL_ARRAY:Array = [
            'http://www.mmo-champion.com/',
            'http://www.bbc.co.uk/news/',
            'http://www.twitch.tv/riotgames/',
            'http://www.stackoverflow.com/'
        ]

        /**
         * 
         */
        public function Controller() 
        {
            addEventListener(Event.ADDED_TO_STAGE, init);
        }

        /**
         * 
         * @param   e
         */
        private function init(e:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            stageWeb = new StageWebView();
            stageWeb.stage = stage;
            stageWeb.viewPort = new Rectangle(0, 80, stage.stageWidth, stage.stageHeight - 50);

            var btn:TextField = new TextField();
            btn.selectable = false;
            addChild(btn);
            btn.text = 'Load URL';
            btn.x = 0;
            btn.y = 10;;
            btn.width = 100;
            btn.height = 30;
            btn.addEventListener(MouseEvent.CLICK, load);

            btn = new TextField();
            btn.selectable = false;
            btn.text = 'Try to GC';
            btn.x = 150;
            btn.y = 10;;
            btn.width = 100;
            btn.height = 30;
            addChild(btn);
            btn.addEventListener(MouseEvent.CLICK, tryGC);

            /// 26,576k
        }

        /**
         * 
         * @param   e
         */
        private function load(e:MouseEvent):void {
            if (!stageWeb) {
                stageWeb = new StageWebView();
                stageWeb.stage = stage;
                stageWeb.viewPort = new Rectangle(0, 80, stage.stageWidth, stage.stageHeight - 50);
            }               

            stageWeb.loadURL(URL_ARRAY[url % 4]);

            url++;
        }

        /**
         * 
         * @param   e
         */
        private function tryGC(e:MouseEvent):void {
            stageWeb.stage = null;
            stageWeb.viewPort = null;
            stageWeb.dispose();
            stageWeb = null;
            System.gc();
        }

    }

}

关于actionscript-3 - HTMLLoader/StageWebView 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24642285/

相关文章:

apache-flex - 关于将 Flex 与 WCF 和 Linq to Entities 结合使用的建议

actionscript-3 - 当窗口没有焦点时如何从控件中移除焦点?(否则当窗口再次获得焦点时它将恢复)

android - 如何与 Adob​​e Air 的锁屏播放器控件集成?

android - 如何使用适用于 Android 的 Adob​​e AIR 设置 Admob

air - 无法使用 app.xml 中指定的图标导出 AIR 发布版本

css - 全局样式覆盖特定组件样式

ios - 定义使用 iOS 相机 Adob​​e Air 拍摄的图像

javascript - ActionScript 3 - ArgumentError : Error #2025: The supplied DisplayObject must be a child of the caller

actionscript-3 - 如何在Adobe Flex中使用bitmapData的setPixels(rectangle, byteArray)方法

java - 跨平台桌面开发