为啥没有事件侦听器或引用的封闭 NetConnection 会留在内存中?

Posted

技术标签:

【中文标题】为啥没有事件侦听器或引用的封闭 NetConnection 会留在内存中?【英文标题】:Why does a closed NetConnection that has no event listeners or references stick around in memory?为什么没有事件侦听器或引用的封闭 NetConnection 会留在内存中? 【发布时间】:2013-01-24 16:25:33 【问题描述】:

似乎如果 flash.net.NetConnection 被实例化并连接到 HTTP URL(例如 AMFphp 网关),则即使在关闭该实例并且唯一引用设置为空。

另一方面,如果实例连接到 null(就像用于播放视频/mp3 文件时所做的那样),则该实例 从内存中清除。

为了澄清,以下连接将留在内存中:

var stickyConn:NetConnection = new NetConnection();
stickyConn.connect("http://myserver/amfphp/gateway.php");
stickyConn.close();
stickyConn = null;

然而,以下连接将立即从内存中清除:

var tempConn:NetConnection = new NetConnection();
tempConn.connect(null);
tempConn.close();
tempConn = null;

我已经尝试过解决这个问题的一些方法:

将客户端设置为空对象(因为客户端的默认值是 NetConnection 本身) 在关闭连接之前,调用connect(null) 关闭连接后,调用connect(null)并再次关闭

以前有人遇到过这个问题吗?有解决办法吗?

【问题讨论】:

你试过 Amfphp 2.1 或更高版本吗? 我没有;我会试一试。这是您自己测试过的东西吗? 我用最新版本的 Amfphp (2.1.1) 对其进行了测试,结果没有任何区别。 我从未真正检查过它或给予太多关注。此外,这是一个客户端问题,因此您不会因此而导致服务器内存过载。但我发现它很有趣,修复它会很酷。 我不关心服务器内存。这是一个 AIR 应用程序,我担心客户端内存。诚然,单个 NetConnection 实例会消耗少量内存;它只是让我感到烦恼,它在不应该的时候徘徊。 【参考方案1】:

我经常使用 AS3 构建重载 FLV/Mp4 播放器。当我使用 Akamai 或 Adob​​e 的内部 NetConnection 类等服务时,我始终牢记 client object.

是调用所有回调方法的 NetConnection 的属性。默认值为此 NetConnection 实例this。如果将客户端属性设置为另一个对象,则会在该对象上调用回调方法。

通过这种方式,您可以轻松了解垃圾收集从未真正以相同方式应用于每个组件。因此,stickyConn = null; 仅停止播放,因为您从未声明过弱引用,所以垃圾收集不知道要查找什么。

我已经根据特定玩家使用不同的方法取得了成功:

通常只需声明NetConnectionObj.client = this 就足够了。但是,如果您的 NetConnection 被扩展或实现了一个接口呢?只需使用 null Dictionary 对象: var d:Dictionary = new Dictionary(true); .从这里垃圾收集将识别“d”作为弱引用并自动转储它;

因此,您的 sn-p 看起来有点像这样: var Dc:Dictionary = new Dictionary(true); NetConnection:NetConnection.client = Dc;

或具有相同意图的一些变体。

我知道这行得通,所以如果您需要帮助,请联系...

【讨论】:

感谢您的帮助,但我相信我们将NetConnection 用于两个非常不同的事情,因此,这种方法对我不起作用。我不是用它来播放视频,而是用它连接到 AMFPHP 网关。我确实测试了您的 sn-p,并且该实例仍在内存中。唯一的区别是现在,内存中还有一个Dictionary 的实例。我希望这个答案对使用NetConnection 进行视频播放的其他人会派上用场。 我不认为它解决了我们的问题。我试过这样做,我也尝试了一些不同的变体。两者都不允许我的 NetConnections 被清除内存。【参考方案2】:

关于 GC 和 Dictionary Objects,我可能对最后一个答案含糊其辞。请考虑这个sn-p。我写得很快,但我试图解释解决问题的概念;主要是因为我之前处理过:

public class Main extends MovieClip 

    private var connection:NetConnection;
    private var __nData:*;
    private var _instance:*;
    private var _closure:Function;
    private var _D:Dictionary;

    public function Main()     
        connection = new NetConnection();
        connection.addEventListener(NetStatusEvent.NET_STATUS, _nsHandle)
        connection.connect(null);
    
    public function _nsHandle(event:NetStatusEvent):void 
        try 
            connection = new NetConnection();
            connection.connect(null);
            connection.client = RegisterForGC(event.target);
            RegisterForGC(connection);
         finally 
            __nData = event.target.netConnection;
                   
    
    public function RegisterForGC(NCObject:*):* 
        _instance = NCObject;
        _closure  = function  ():void       
        _listener = function (e:Event):void 
        _D = new Dictionary(true);
        _D[_listener] = "A";
        _D[_instance] = "B";
        _D[_closure]  = "C";
        try 
            new LocalConnection().connect( "A" );
            new LocalConnection().connect( "B" );
         catch (anything:*)  
        return _instance;
    

【讨论】:

对不起,我在回答问题时遇到了一点麻烦。【参考方案3】:

我不确定,但您的示例似乎表明您在舞台/框架上声明您的变量。

关闭();这就是你所需要的所有工作但是...... 根据我在 NetConnection 中发现的某些原因,除非所有变量/函数都在 External 类中声明,例如。公共变量公共函数, 即使在使用 close(); 后它仍保留在内存中;

通过一个音频流项目解决了这个问题,我拔掉了头发。 但是,一旦我将所有编码移至外部类, close();实际上关闭了连接。

如果您的代码在舞台上的框架上或在 MC 中,我会创建一个类并在所述 External Class.as 中声明变量和函数,并且由于某些愚蠢的原因它可以工作。

希望这会有所帮助。

【讨论】:

欣赏响应,但代码都在一个外部类中。上面的代码是一个简单的示例,用于演示手头的问题。【参考方案4】:

您是否正在使用 NetStream 对象,并且在完成后不处理它?我之所以问,是因为我很少看到后面没有 NetStream 对象的 NetConnection。

【讨论】:

不涉及 NetStream 对象。 NetStream 与 NetConnection 一起用于流式传输视频/声音。在这种情况下,NetConnection 用于连接到 AMFPHP 网关。 虽然不是特定问题的解决方案,但我发现此答案很有帮助。在对任何问题进行故障排除时,能够查看“常见嫌疑人”列表是很不错的。 该问题涉及客户端中没有剩余引用或任何内容的事实,甚至没有事件侦听器。 NetConnetion 已关闭,它的引用被彻底删除,一切。我唯一注意到的是,FMS 似乎仍然非常坚定地假设客户端仍然存在,直到它的删除空闲客户端超时开始。

以上是关于为啥没有事件侦听器或引用的封闭 NetConnection 会留在内存中?的主要内容,如果未能解决你的问题,请参考以下文章

为啥没有为 primefaces SelectManyCheckbox 调用事件侦听器?

为啥我的事件监听器没有在 laravel 5 中触发?

为啥“事件动画”(没有侦听器)在 A-Frame 0.6.1 中有效,但在 0.9.0 中无效?这是一个错误吗?

为啥 jQuery 选择事件侦听器会触发多次?

为啥 jQuery 单击事件侦听器未在 WooCommerce 按钮上注册?

JAVA的事件委托机制和垃圾回收机制