3

我在 AS3 中编程了一段时间,发现一个非常奇怪的字符串问题,没有明显的原因挂在内存上,下面的程序只是用随机字符串更改 label.text 属性,它工作正常但是当我查看 Flex 分析器我注意到字符串的数量在稳步增加,我尝试执行垃圾收集器但没有帮助我。

这是内存泄漏吗?我该如何解决?

据我所知,这些字符串应该由垃圾收集器收集,因为没有对象引用它们,但并非所有字符串都发生这种情况。

这是 Flex 分析器的代码和屏幕截图,显示了 String 实例的数量。

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)">
<s:layout>
    <s:BasicLayout/>
</s:layout>
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;

        protected var t:Timer=new Timer(10);

        protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
        {
            t.addEventListener(TimerEvent.TIMER,listener,false,0,true);
            t.start();
        }

        protected function listener(e:Event):void
        {
            var s:String=Math.random()+"-->";
            this.fx(s);
            s=null;
        }

        protected function fx(s:String):void
        {
            this.label.text=s;
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label id="label" y="39" left="10" right="10" text="Label"/>
</s:WindowedApplication>

抱歉,不到 10 分,这是分析器截图 http://imageshack.us/a/img11/9716/stackw.png

解决了

Baris 和 Loxxy,你是对的,我做了一些更改以隔离问题,它增长到 ~30Mb,然后垃圾收集器释放一些内存,它永远不会回到 ~2mb(起点),但图表开始从~20mb 到 ~30mb 一遍又一遍。

这是测试这个的代码

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)">
<s:layout>
    <s:BasicLayout/>
</s:layout>
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;
        protected var maxMemoryUsage:Number=0;
        protected var i:Number=0;

        protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
        {
            setTimeout(Fx,20);
        }

        protected function Fx():void
        {
            if(i++%1024==0) 
            {
                var mem:Number=System.totalMemory;
                this.maxMemoryUsage = mem>this.maxMemoryUsage?mem:this.maxMemoryUsage;
                trace(this.maxMemoryUsage + ' / ' + mem);
            }

            var s:String="";
            s+=Math.random().toString()+"qwertyuiu...1024 random chars...iiwqe";
            this.aSimpleString=s;
            setTimeout(Fx,20);
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
    <fx:String id="aSimpleString"/>
</fx:Declarations>
</s:WindowedApplication>

也调用 System.gc() 什么也没做,也许 gc 需要一些暂停才能运行。

4

3 回答 3

4

垃圾收集器将随时运行。通常它发生在分配新对象时,但如果内存使用率不高,它可能不会发生在您的情况下。

您可以尝试调用System.gc()以查看它是否释放了这些字符串。但是您不应该在生产代码中使用它。

有关更多信息,请参阅答案。

于 2012-10-10T14:54:27.163 回答
2

你没有写一个计时器来运行低于推荐的延迟吗? new Timer(10);

这里

不推荐低于 20 毫秒的延迟。定时器频率限制为每秒 60 帧,这意味着低于 16.6 毫秒的延迟会导致运行时问题。

正如 Baris 之前所说,人们在他们的应用程序中会遇到大量内存,这就是神奇的 gc 到达解决内存问题的时候。除此之外,您既不需要担心它,也不能手动对其进行任何操作。

于 2012-10-10T15:54:19.853 回答
1

这可能与Master Strings相关,这是Flash 运行时用来最小化相关字符串数据块的冗余分配的内存优化。

您可以在这篇博客文章Flash String 怪异中阅读有关真实世界影响的详细分析。

以下是该帖子中与 SO 相关的一些亮点:

结果

  • 如果您从长字符串中取出部分字符串,它将保留长字符串。
  • 如果您加入超过 2 个字符串,它将保留第二个字符串作为主字符串。
  • 如果您循环并一起添加字符串,它将与上面相同,它将开始保留您第三次添加的主字符串。
  • 循环字符串测试似乎表明每个字符串都可以有一个父链。
  • 这不能被遵守,因为我们只能访问返回链根的“getMasterString()”。

…</p>

结论

  • 字符串有“父字符串”
  • XML 保持对它的父字符串的引用
  • 字符串可能会泄漏内存
  • 由于上述原因,控制台图形似乎泄漏
于 2013-01-08T00:16:05.897 回答