Каждый раз, когда вы используете «новое» ключевое слово для создания объекта, вы ставите свою заявку на кусок памяти [1]. Итак, скажем, вы делаете uint, написав var exampleUint:uint = new uint();
. ActionScript говорит компьютеру «эй ... Мне нужно ... четыре байта памяти», на который компьютер отвечает «хорошо, используйте четыре байта, начиная с [некоторого адреса памяти, например 0x7B3208C1]» [2] , Поэтому, когда вы говорите var someString:String = "blah";
, вы претендуете на пробел в памяти, заполните его некоторой информацией (в данном случае это "blah"
), создайте метку (в данном случае это someString
) и bind ярлык для этого пространства в памяти.
Теперь метка фактически не связывается с самими данными, она связывается с местом в памяти, содержащей данные. Это должно показаться запутанным, потому что это так, но по определенным причинам оно вызывает целомудренное чувство. Все объекты в ActionScript имеют значения reference, что означает, что объект содержит адрес памяти некоторой части данных, а не самих данных. Это контрастирует с объектами, которые являются типами value, где метка ассоциируется с самими данными. Не волнуйтесь о деталях типов значений, потому что это не в ActionScript, поэтому для ваших целей я включаю его строго для контраста. Хорошо, смущенный? Вы, вероятно, должны быть, потому что весь этот абзац совершенно бесполезен и, возможно, даже ненужен, но старайтесь держать его в задней части головы, потому что может иметь какое-то отношение к вашей проблеме.
Теперь, когда эта метка исчезла (например, она выходит из scope, так что теперь someString
не имеет смысла), удаляется только метка someString
. Итак, для этого примера, если вы скажете someString = null;
, строка "blah"
на самом деле все еще в памяти, но метка someString
не ссылается на эту часть информации, она ссылается на адрес памяти the null object (опять же, подробности). Нам нужен способ указать на компьютер «вы знаете, что [whatSize] кусок памяти, который я утверждал, начиная с [whateverAddress]? Хорошо, я закончил с этим сейчас, чтобы кто-то еще мог использовать эту часть памяти».Gabage collection - это автоматический процесс восстановления памяти, о котором вы заявили, не беспокоясь об этом самостоятельно. На языках без сбора мусора 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, потому что все uints имеют одинаковый размер, поэтому я могу с уверенностью сказать, что знаю, что это будет четыре байта. Строки разные; они занимают объем памяти, пропорциональный количеству символов, которые они содержат, поэтому было бы немного более двусмысленно использовать String для обоих примеров.
[3]: Ключевое слово ActionScript delete
не для этой цели, поэтому не пытайтесь использовать его таким образом, хотя это будет иметь логический смысл и было бы очень полезно.
[4]: Flash использует стратегию стиля mark-and-sweep, более конкретно подробную информацию о которых можно прочитать here. [5]: На самом деле, это жирный шрифт, потому что метод addEventListener использует closures, но у меня есть довольно слабое понимание этого для начала, поэтому я не могу действительно сварить его на обычного человека.
В AS3 вы можете создать слабую ссылку на прослушиватель событий, который позволит отображать изображение (например) для сбора мусора. –
Это addEventListener, и это наоборот. Функция, прослушивающая событие, не будет собираться, пока изображение существует. –
Вы абсолютно правы. Спасибо, что указал на мои ошибки. –