2012-10-10 63 views
3

我一直在AS3编程一段时间,发现一个非常奇怪的问题,因为没有明显的理由挂在内存中,下面的程序只是改变label.text属性随机字符串,它工作正常,但当我看着Flex Profiler我注意到字符串的数量稳步增加,我试图执行垃圾收集器,但没有帮助我。AS3字符串内存泄漏

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

据我所知,这个字符串应该被垃圾收集器收集,因为没有对象引用它们,但这并不是所有的字符串都会发生。

下面是代码和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

解决

巴里斯和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希望以运行一些暂停。

+1

如果在紧密的循环中非常快速地生成字符串,可能是垃圾收集器没有足够的时间来释放字符串。我只是在这里猜测,自从我做AS3工作已经有一段时间了。 10ms似乎并不是那么快,但我在AS3中看到了一些陌生的东西。你尝试过一个更慢的计时器吗? – xxbbcc

+0

是的,实际上这是一个测试im与其他程序没有使用计时器相同的问题,也尝试通过Flex profiler接口强制垃圾收集器 – DooMMcQ

+0

或者你可以尝试安装不同的播放器版本 - 我见过Adobe介绍当他们发布一个新版本时,他们经常会遇到主要的Flash Player错误。您的当前版本有可能存在GC错误。你的代码看起来正确。 – xxbbcc

回答

4

无论何时感觉,垃圾收集器都会运行。通常它发生在新对象的分配上,但如果内存使用率不高,它可能不会发生在您的情况中。

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

请参阅this回答获取更多信息。

+1

但是,您不应该在生产代码中使用该版本。 =>其实你不能,它只能在调试闪存播放器上使用。 – blue112

+0

添加了一个按钮来调用System.gc(),但仍然是相同的行为,即时让程序运行以便使用更多内存,字符串实例现在使用6mb的80%,这是我的程序正在分配的总内存 – DooMMcQ

+0

是啊6MB没什么,就像我说的那样,当GC感觉像GC时就会释放东西。你的代码没有错,实际上你甚至不需要将字符串作为空值,因为它是一个局部变量,并且在函数结束时超出范围。 –

2

您是否写过计时器以在推荐的延迟以下运行? new Timer(10);

here

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

正如Baris早些时候所说的,人们在其应用程序中遇到大量内存,这就是当神奇的gc到达解决内存问题的时候。除此之外,你不需要担心它,也不能手动做任何事情。

+0

将计时器更改为500毫秒,通过连接更多随机数来增加字符串的大小以增加内存使用量,但没有区别:( – DooMMcQ

0

这可能与Master Strings,使Flash运行时使用,以尽量减少串数据的相关区块的冗余分配的内存优化。

你可以阅读关于这个博客帖子Flash String weirdness现实世界的影响进行详细分析。

下面是帖子的一些亮点是相关的SO:

结果

  • 如果你从一个长的字符串部分字符串,它会保持很长的字符串。
  • 如果您加入2个以上的字符串,它会将第二个字符串保留为主字符串。
  • 如果您循环并添加字符串,它将与上面相同,它将从第三个 加法开始保留主字符串。
  • 循环字符串测试似乎表明每个字符串都可能有父母链。
  • 这不能符合,因为我们只能访问'getMasterString()',它返回链的根。

...

结论

  • 字符串有 '父字符串'
  • XML保持引用到它的父字符串(S)
  • 字符串会出现内存泄漏
  • 控制台由于以上原因,图表似乎泄漏