【问题标题】:If an object is garbage collected in Flash, are the reference counters of objects it references decremented automatically?如果一个对象在 Flash 中被垃圾回收,它引用的对象的引用计数器是否会自动递减?
【发布时间】:2011-06-20 21:04:25
【问题描述】:

前几天我在考虑 Flash GC,并提出了一个问题,即引用计数在以下 4 类场景中如何工作(假设 GuiMain 是电影的文档类):

package com.gui {     
import flash.display.MovieClip;         
public class GuiMain extends MovieClip {         
 private var button1Handle:Button1;         
 public function GuiMain() {             
  // constructor code             
  button1Handle = new Button1();             
  addChild(button1Handle);            
  killButton1();         
 }                 
 public function killButton1(){             
  removeChild(button1Handle);             
  button1Handle = null;         
 }     
}     
}



package com.gui {     
import fl.controls.Button;    
import flash.display.*;         
public class Button1 extends Sprite {         
 private var button2Handle:Button2;         
 private var tester:Test;         
 public function Button1() {             
  // constructor code            
  button2Handle = new Button2();             
  tester = new Test();         
 }     
}     
}



package com.gui {         
public class Button2 {         
 public function Button2() {             
  // constructor code         
 }     
}     
}


package com.gui {     
import flash.display.MovieClip;     
import flash.events.Event;             
public class Test extends MovieClip{         
 public function Test() {             
  // constructor code            
  addEventListener(Event.ENTER_FRAME, yellLoudly);         
 }                 
 public function yellLoudly(e:Event){                         
  trace("AAAH!!!");         
 }     
}     
}

当在 Button1 中创建 Button2 和 Test 实例时,我希望它们的引用计数器会增加。问题是,当创建它们的 Button1 对象从显示列表中删除并清空时,它们的引用计数器是否会相应减少?我测试了这段代码,Test 类中的事件监听器似乎关闭了,但这并不一定意味着它或 Button2 实例有资格进行 GC。即使是,也可能只是在 Mark and Sweep 下,这比基于引用计数的 GC 慢。

一个明显的解决方案是让 Button1 类从它所做的/空引用中删除侦听器,当它需要被删除时,如下所示:

package com.gui {     
import fl.controls.Button;     
import flash.display.*;         
public class Button1 extends Sprite {         
 private var button2Handle:Button2;         
 private var tester:Test;         
 public function Button1() {             
  // constructor code             
  button2Handle = new Button2();             
  tester = new Test();         
 }                 
 public function destroyRefs(){                   
  button2Handle = null;                   
  tester.removeEventListener(Event.ENTER_FRAME, tester.yellLoudly);                   
  tester = null;            
 }     
}     
}

但是在一个真正的程序中,我可能会处理来自不同类的对同一对象的多个引用(通过在构造函数中传递原始引用)不会将一个类中的引用设置为 null 导致 all 的值对同一对象的其他引用也变为空?那肯定是不可取的……

主要问题如下:当对 Button1 的唯一引用被清空时,它所引用的所有对象的引用计数器是否都会减少(立即或当 Button1 对象被垃圾回收时)?强>

另外,有没有办法通过 Flash 调试器查看实时存在的对象的所有实例和/或其引用计数值?像这样的详细分析器确实有助于解决这些问题......

谢谢, CCJ

【问题讨论】:

  • 啊!你必须对这种格式做点什么!
  • 我是不是错过了什么,你在哪里添加测试人员到舞台?
  • 测试者不必添加到显示列表中;它的唯一目的是用明确的文本填充调试控制台。

标签: flash apache-flex actionscript-3 garbage-collection


【解决方案1】:

无耻的自我推销,但这应该对你有帮助:http://divillysausages.com/blog/tracking_memory_leaks_in_as3

【讨论】:

  • 如果你想链接到你的文章,你的答案应该表明它与问题的相关性。
  • 我认为链接说明了它:tracking_memory_leaks_in_as3。但是,是的,最好给出一个小总结。 (也可以进行更有效的自我宣传。)
  • 优点 :) 它涵盖了 as3 垃圾收集的基础知识,包括引用计数方法和标记和清除,以及为您提供帮助跟踪内存泄漏和轻松查看对象是否存在的工具正确删除,以及如何在调试和发布模式下调用垃圾收集器
  • 另外,@jeff,flashdevelop 和 flash builder 都带有分析器,可让您查看创建了多少对象以及仍有多少对象存在
  • 感谢您的链接;非常翔实!此外,我在这里找到了 Flash Builder 分析器的开源替代方案:jpauclair.net/flashpreloadprofiler 尚未对其进行测试,但它的演示看起来很棒。
【解决方案2】:

我不认为 AS3 在引用计数方面。如果在 Button1 中创建的那些对象只能通过 Button1 访问,那么一旦您将 Button1 设为空,它们就有资格进行 GC。例外情况是事件侦听器,您必须清理它们,否则这些对象不会被清除。 Flash 不再考虑没有对象在监听。

【讨论】:

  • 是的,但是如果可以从 Button1 外部访问对象怎么办?问题是我不想以永远无法达到 0 的类之间“共享”的对象的引用计数结束,因为另一个引用它们的对象不再存在,但未能显式地清空它之前所做的引用是GC'd。如果一个对象的引用在被 GC 时自动清空,这不是问题。所以这才是真正的问题——当一个对象被 GC 时,引用是否被清空了?
  • 据我所知,您无需担心引用计数。如果 Object1 和 Object2 都引用了 Object3,那么一旦两个引用都被清空,Object3 将有资格进行 GC,它们何时执行的时间无关紧要。
【解决方案3】:

这个演示文稿http://onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf 很好地描述了垃圾收集是如何在 AVM2(运行 AS3 的虚拟机)中实现的。

【讨论】:

    【解决方案4】:

    哦,好问题:)

    据我所知,Mark and Sweep 仅用于引用计数事件侦听器,因为它们是唯一可以拥有“弱侦听器”的侦听器。其他一切都是直接的内存引用计数。本质上,您最大的问题是清理事件侦听器,但是如果事件侦听器在您的类中(侦听自身,或者是子事件,甚至是外部事件),如果对象在整个应用程序中被取消引用,则它们应该被正确地 GC(不要将其存储在其他地方)。

    如果您让对象或属性公开可见,则其他类可能会引用它们,并且可能会阻止您的类的 GC(这实际上取决于它是如何被引用的)。唯一可以解决的问题是尝试尽可能地封装(一个类处理它自己的解引用;查看 IDisposable),以便其他人无法引用并尝试遵守良好的编码实践(防止意大利面条式代码)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多