Каждый раз, когда вы используете ключевое слово «new» для создания объекта, вы размещаете заявку на куске памяти [1]. Допустим, вы делаете вывод, написав var exampleUint:uint = new uint();
. ActionScript говорит компьютеру «эй ... мне нужно, как ... четыре байта памяти.», На что компьютер отвечает «хорошо, круто, используйте четыре байта, начиная с [некоторый адрес памяти, например, 0x7B3208C1]» [2] , Поэтому, когда вы говорите var someString:String = "blah";
, вы запрашиваете место в памяти, заполняете его некоторой информацией (в данном случае это "blah"
), создаете метку (в данном случае это someString
) и bind метка для этого пространства в памяти.
Теперь метка фактически не ассоциируется с самими данными, она ассоциируется с местом в памяти, содержащим данные. Это должно показаться запутанным, потому что это так, но по определенным причинам это имеет смысл. Все объекты в ActionScript являются ссылочными типами, что означает, что объект содержит адрес памяти некоторого фрагмента данных, а не сами данные. Это отличается от объектов типа value , где метка связана с самими данными. Не беспокойтесь о деталях типов значений, потому что это не в ActionScript, поэтому для ваших целей я включаю его исключительно для контраста. ОК, запутался? Вероятно, так и должно быть, поскольку весь этот абзац излишне специфичен и, возможно, даже не нужен, но старайтесь держать его в затылке, потому что может как-то иметь отношение к вашей проблеме.
Теперь, когда эта метка исчезла (например, она выходит за пределы scope , поэтому теперь someString
не имеет смысла), удаляется только метка someString
. Так что для этого примера, если вы скажете someString = null;
, строка "blah"
на самом деле все еще находится в памяти, но метка someString
не ссылается на этот фрагмент информации, она ссылается на адрес памяти нулевого объекта (опять же, подробности). Нам нужен способ указать компьютеру: «Вы знаете, какой кусок памяти [whatSize] я требовал, начиная с [whatAddress]? Что ж, теперь я покончил с этим, чтобы кто-то другой мог использовать этот кусок памяти». Коллекция Gabage - это автоматический процесс восстановления памяти, на который вы претендовали, не беспокоясь об этом самостоятельно. В языках без сборки мусора new
имеет ключевое слово дополнение, которое специально освобождает память, связанную с объектом [3], но ActionScript не имеет этого; ты просто берешь кусок памяти и забываешь об этом.
Где-то вдоль строк, вы, возможно, создали другую переменную и сослались на этот фрагмент данных, var someOtherString:String = someString;
, поэтому мы не можем просто сказать: «Хорошо, метка someString
исчезла, так что давайте избавимся от данных что он ссылается ", потому что мы не знаем наверняка, что someString
является единственной ссылкой на эти данные. Метод, в котором это делается, различается в зависимости от языка и системы сборки мусора, но основное действие в ActionScript заключается в следующем: время от времени (особенно если Flash в настоящее время занимает много памяти) сборщик мусора просматривает все объекты в текущем SWF и находит все объекты, на которые нет ссылок [4]. Таким образом, для нашего предыдущего примера, если someString
было единственной ссылкой на строку "blah"
и someString
выходит из области видимости, то "blah"
не связан ни с одной меткой и поэтому полностью недоступен для Flash. В следующий раз, когда будет запущен сборщик мусора, он обнаружит это и затем сообщит системе, что он сделал с этим фрагментом памяти.
Теперь, конкретные детали вашей конкретной проблемы трудно сказать, не глядя на источник, но я могу вам сказать, что одна из вещей, которая часто вызывает проблемы, - это прослушиватели событий. Иногда вы можете создать функцию и добавить ее в качестве прослушивателя событий. Теперь само событие имеет ссылку на эту функцию [5], поэтому, если функция выходит из области видимости, есть ссылка на нее, и функция не может быть собрана сборщиком мусора (помните, функции являются объектами в ActionScript). Вы можете либо удалить обработчик событий вручную, вызвав removeEventListener (я бы не рекомендовал это сделать), либо установить параметр useWeakReference
в ваших вызовах на addEventListener () на true
. Слабая ссылка не распознается сборщиком мусора, поэтому установка useWeakReference
в true
предотвращает ситуацию, когда у вас есть функция, которая должна быть подобрана сборщиком мусора, но это не потому, что кто-то ссылается на него как на слушателя событий. Судя по большому количеству слушателей mouseEvent в вашем проекте, это может быть причиной. Если у вас есть Flex Builder, вы можете использовать профилировщик, чтобы увидеть, сколько у вас закрытий методов; если они поднимаются и никогда не падают, это, вероятно, ваша проблема.
[1]: имейте в виду, что это также относится к ситуациям, когда вы создаете объект без использования ключевого слова new
, например, если вы пишете var exampleInt:int = 5;
.
[2]: Я выбрал uint, потому что все uint имеют одинаковый размер, поэтому я могу с уверенностью сказать, что знаю, что это будет четыре байта. Строки разные; они занимают объем памяти, пропорциональный количеству содержащихся в них символов, поэтому было бы немного двусмысленно использовать String для обоих примеров.
[3]: ключевое слово ActionScript delete
не для этой цели, поэтому не пытайтесь использовать его таким образом, даже если это имело бы логический смысл и было бы очень полезно.
[4]: Flash использует стратегию стиля mark-and-sweep , более подробные сведения о которой можно прочитать здесь .
[5]: На самом деле, это полужирная ложь, потому что метод addEventListener использует замыкания , но у меня довольно слабое понимание этого, поэтому я не могу свести его к английскому обычному человеку.