Почему закрытый NetConnection, у которого нет прослушивателей событий или ссылок, остается в памяти?

Кажется, что если flash.net.NetConnection создается и подключается к URL-адресу HTTP (например, к шлюзу AMFPHP), этот экземпляр никогда не извлекается сборщиком мусора даже после того, как он был закрыт, а единственная ссылка имеет значение null.

С другой стороны, если экземпляр подключен к 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) и снова закройте его.

Кто-нибудь сталкивался с этой проблемой раньше? Есть ли этому решение?


person Marcela    schedule 08.02.2013    source источник
comment
Вы пробовали это с Amfphp 2.1 или более поздней версии?   -  person Marco Aurélio Deleu    schedule 11.02.2013
comment
Я нет; Я попробую. Это то, что вы проверили на себе?   -  person Marcela    schedule 13.02.2013
comment
Я проверил это с последней версией Amfphp (2.1.1), и это не имело значения.   -  person Marcela    schedule 13.02.2013
comment
Я никогда не проверял это и не уделял этому особого внимания. Кроме того, это проблема на стороне клиента, поэтому у вас не будет перегрузки памяти сервера из-за этого. Но мне показалось это интересным, и было бы здорово это исправить.   -  person Marco Aurélio Deleu    schedule 13.02.2013
comment
Я не беспокоюсь о памяти сервера. Это приложение AIR, и меня беспокоит память на стороне клиента. Конечно, один экземпляр NetConnection потребляет минимальный объем памяти; меня просто беспокоит, что он зависает, когда не должен.   -  person Marcela    schedule 13.02.2013
comment
Убедились ли вы, что в вашем NetConnection нет прослушивателей событий? Вы, вероятно, уже сделали это, но это стоит перепроверить.   -  person mfa    schedule 10.02.2014
comment
@mfa, да, я убедился. Код, который вы видите выше (без прослушивателей), является именно тем кодом, который демонстрирует утечку.   -  person Marcela    schedule 10.02.2014


Ответы (4)


Я довольно часто собирал сильно загруженные проигрыватели FLV/Mp4 с использованием AS3. Когда я использую такой сервис, как Akamai или внутренний класс Adobe NetConnection, я всегда учитываю client объект.

это свойство NetConnection, для которого вызываются ВСЕ методы обратного вызова. По умолчанию используется этот экземпляр NetConnection this. Если вы установите свойство client для другого объекта, для этого объекта будут вызываться методы обратного вызова.

Таким образом, вы можете легко понять, почему сборка мусора никогда не применялась к каждому компоненту одинаково. Итак, когда stickyConn = null; только останавливает воспроизведение, поскольку вы никогда не объявляли слабую ссылку, сборщик мусора понятия не имеет, что искать.

Я добился успеха с различными методами, основанными на конкретном игроке:

Обычно достаточно просто указать NetConnectionObj.client = this. Но что, если ваш NetConnection расширен или реализует интерфейс? Просто используйте объект null Dictionary: var d:Dictionary = new Dictionary(true); . Отсюда сборка мусора распознает «d» как слабую ссылку и автоматически сбрасывает ее;

Следовательно, ваш фрагмент будет выглядеть примерно так:
var Dc:Dictionary = new Dictionary(true);
NetConnection:NetConnection.client = Dc;

или некоторые вариации с тем же намерением.

Я знаю, что это работает, так что обращайтесь, если вам нужна помощь...

person Leonardo.Martinez    schedule 13.02.2014
comment
Спасибо за попытку помочь, но я считаю, что мы используем NetConnection для двух совершенно разных целей, и по этой причине этот метод не работает для меня. Я не использую его для воспроизведения видео, я использую его для подключения к шлюзу AMFPHP. Я проверил ваш фрагмент, и экземпляр все еще торчит в памяти. Единственная разница в том, что теперь в памяти также висит экземпляр Dictionary. Я надеюсь, что этот ответ пригодится другим, кто использует NetConnection для воспроизведения видео. - person Marcela; 13.02.2014
comment
Я не думаю, что это решает нашу проблему. Я пытался сделать это, и я также пробовал несколько различных вариантов этого. Ни один из них не позволил моим NetConnections очистить память. - person Panzercrisis; 14.02.2014

Возможно, я был расплывчат с последним ответом в отношении GC и объектов словаря. Пожалуйста, примите во внимание этот фрагмент. Я написал это быстро, но я пытаюсь объяснить концепцию того, что решает вашу проблему; в основном, потому что я имел дело с этим раньше:

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;
    }
}
person Leonardo.Martinez    schedule 14.02.2014
comment
Извините, у меня возникли небольшие проблемы с ответом. - person Panzercrisis; 14.02.2014

Я не уверен, но ваш пример, кажется, предполагает, что вы объявляете свои вары на сцене/фрейме.

Закрыть(); это все, что вам нужно, чтобы это работало, ОДНАКО.... из того, что я нашел с NetConnection, это по какой-то причине, если только все vars/функции не объявлены во внешнем классе, например. public vars public function, она остается в памяти даже после использования close();

Вырвал себе волосы, чтобы понять это с проектом потокового аудио. Однако как только я перенес весь код во внешний класс, close(); фактически закрыл соединение.

Если ваш код находится в кадре на сцене или внутри MC, я бы создал класс и объявил vars и функции в указанном внешнем классе. as, и по какой-то глупой причине он работает.

Надеюсь это поможет.

person Sean Carroll    schedule 02.05.2016
comment
Спасибо за ответ, но весь код находится во внешнем классе. Приведенный выше код является простым примером, демонстрирующим проблему. - person Marcela; 03.05.2016

Вы используете объект NetStream и не избавляетесь от него по завершении? Я спрашиваю только потому, что редко вижу NetConnection без объекта NetStream далеко за ним.

person Nathan    schedule 14.02.2013
comment
Объект NetStream не задействован. NetStream используется вместе с NetConnection для потоковой передачи видео/звука. В этом случае NetConnection используется для подключения к шлюзу AMFPHP. - person Marcela; 16.02.2013
comment
Хотя это и не решение конкретной проблемы, я нашел этот ответ полезным. Приятно иметь список «обычных подозреваемых», на который стоит обратить внимание при устранении любой проблемы. - person mfa; 10.02.2014
comment
Вопрос касается того факта, что в клиенте нет остаточных ссылок или чего-либо еще, даже прослушивателей событий. NetConnetion закрыт, его упоминания тщательно удалены, все. Единственное, что я заметил, это то, что FMS все еще, похоже, решительно настроена предположить, что клиент все еще присутствует, пока не сработает тайм-аут удаления бездействующего клиента. - person Panzercrisis; 14.02.2014