【问题标题】:Memory leak when loading SWF加载 SWF 时内存泄漏
【发布时间】:2011-06-13 12:57:21
【问题描述】:

我有一个加载器 SWF,它在后台运行一些代码并加载其他 SWF。使用此代码:

private function loadScreensaver():void {
            screensaverSWF = new Loader();
            var req:URLRequest;
            switch(areaNumber){
                case 1 :
                    req = new URLRequest("exNorthernFrontierScreensaver.swf");
                    break;
                case 2 :
                    req = new URLRequest("exRomanEmpireScreensaver.swf");
                    break;
                case 3 :
                    req = new URLRequest("exRomanCarlisleScreensaver.swf");
                    break;
                case 4 :
                    req = new URLRequest("exRomanBritainScreensaver.swf");
                    break;
            }
            screensaverSWF.load(req);
            addChild(screensaverSWF);
            GAME_STATE = SCREENSAVER;
        }

我加载屏幕保护程序并将其添加到舞台。使用 MonsterDebugger 我可以看到内存从大约 80mb 稳步上升,直到应用程序退出(我使用 windows 投影仪)。我无法解决的是为什么,屏幕保护程序 SWF 没有附加代码,只是一些淡入淡出的时间线动画。 知道这里发生了什么吗?

编辑: 我一直在测试,发现我有一个图像开始阶段然后补间打开和关闭并被删除。当它循环时,它会再次添加到内存中,就好像仍然保留第一个图像一样。这一切都在时间线上完成。

编辑2: http://www.rezmason.net/blog/caching-timeline-objects-in-flash 这似乎是问题,但没有给出解决方案。此屏幕保护程序每天最多可运行 6 小时,在 2 小时后退出。

【问题讨论】:

    标签: flash actionscript-3


    【解决方案1】:

    您永远不会从内存中清除外部加载的 swf。一旦你从外面加载了一些东西,如果你之后看到内存下降,那将是一个奇迹。因此,如果您发现您可能在 swf 的生命周期内多次“加载”同一个资产,您需要保留最初加载的资产并重新使用它。该函数看起来可能会被重复调用,而您每次执行此操作时只是重新加载已加载的资产。

    那样的话,最糟糕的情况是你只会让每个屏幕保护程序都挂着,但每个屏幕保护程序只有一个。

    【讨论】:

    • 我现在没有卸载它,这会在稍后发生,但在播放时,它只是重复,它正在建立更多的记忆......
    • 那句话中有很多“它的”,但没有明确指出每个指的是什么。无论如何,我的意思是您通常不能卸载它们。 .unload 完全失败,并且 .unloadAndStop 并没有给出更好的结果。这就是为什么我说要挂在你加载的对象上,只是吃掉内存损失,而不是通过一遍又一遍地重新加载相同的外部资产来做你目前正在做的事情。停止加载的剪辑,并将它们从舞台上移除,但保留引用并重用它们,而不是使用新的加载器来抓取您之前已经加载过一次的资产。
    • 抱歉不是很清楚。目前我没有重复这个功能。屏幕保护程序 swf 加载一次,然后立即播放,同时播放内存构建。它只是重复时间轴动画
    • 如果负载真的只发生一次,那就完全是另一回事了。您是否单独分析了加载的 swf 以查看它们本身是否存在某种泄漏?
    • 是的,我刚刚完成了这项工作,添加了一个文档类并添加了调试器以查看内存使用情况,但它仍在攀升。不知道为什么,唯一的代码是在其中一个实例中使用 gotoAndPlay 命令
    【解决方案2】:

    OK 解决了问题。它似乎在动画结束时删除图像,然后循环动画会导致它们重复添加到内存中。图像现在要么变得不可见,要么在接近尾声时移出舞台,以便重复使用。

    【讨论】:

      【解决方案3】:

      虽然您永远无法从内存中卸载远程 SWF 中的代码和任何嵌入图像,但您通常可以释放大量已创建的数据。一种简单的方法是遍历 swf 中的每个显示子项并在每个子项上调用 removeChild。为了更好地衡量,我还为每个Movieclip 类型的孩子打电话给stop()。这将有助于减少实例化用于显示的图像/动画的内存占用。

      【讨论】:

        【解决方案4】:

        我不确定这是否能解决这个问题,但是每当加载新代码时,它都会加载到当前的 ApplicationDomain 中,并且您不能只从应用程序域中卸载“一些”代码。也许如果你为每个加载的 swf 创建一个新的 ApplicationDomain,一旦你取消引用它,它可能会被垃圾收集。

        screensaverSWF.load(req, new LoaderContext(false, new ApplicationDomain()));
        

        【讨论】:

        • 在单独运行时,加载的内容本身似乎存在缓慢的内存泄漏,因此 ApplicationDomain 与该问题无关。
        【解决方案5】:

        如果您再次遇到此问题,SWFWire DebuggerObject 选项卡可能会通过显示已添加或删除的对象列表来帮助您查找内存泄漏(假设一切都是 AS3) .

        【讨论】:

          猜你喜欢
          • 2016-08-10
          • 1970-01-01
          • 1970-01-01
          • 2017-02-28
          • 1970-01-01
          • 2011-07-07
          • 2017-01-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多