Утечки памяти и их устранение
Запись была переработана и обновлена.
1. Введение
Многие начинающие флэшеры, как и я в свое время, не имеют представления об освобождении памяти от использованных, либо недооценивают данный раздел программирования.
В ходе разработки приложений объекты, которые были использованы и более не являются необходимыми в большинстве случаев остаются в памяти, если не позаботиться об их уничтожении. Оставаясь в памяти «мусор» может вызвать проблемы с производительностью, что для конечного пользователя не окажется радостным событием.
В данной статье раскрываются методы очистки памяти от «мусора».
2. Откуда берется мусор, и как образуются утечки памяти (memory leaks)?
Во as3 вы никогда не работаете напрямую с объектом (классы, массивы и т.д.), каждый раз вы обращаетесь по ссылке к данному классу.
var instanceLink : Sprite = new Sprite();
В данном примере мы создаем новый экземпляр класса Sprite, и instanceLink есть ничто иное как ссылка указывающая на данный экземпляр класса.
2.1 Мертвые объекты
AS3 не предоставляет «нативного» (native) метода для уничтожения текущего экземпляра класса, то есть деструктора. Вместо тотального контроля памяти программистом, как это реализовано например в C++, используется механизм под названием сборщик мусора (Garbage Collector), который очищает память от «мертвых объектов» при каждой итерации. Мертвым объектом считается, тот на который не существует ни одной ссылки.
Таким образом, если мы напишем:
var instanceLink : Sprite = new Sprite(); var doubleLink : Sprite = instanceLink; instanceLink = null;
…то экземпляр класса Sprite не будет удален из памяти, потому что doubleLink все еще указывает на него.
2.2 Список отображения
secondSprite.addChild(instanceLink); instanceLink = null;
В список отображения (display list) secondSprite заносится экземпляр спрайта, даже после очищения ссылки на экземпляр, он никуда не денется и из памяти удален не будет, так как ссылка на него находится в display list’e, следовательно чтобы удалить объект из памяти необходимо убрать его из списка отображения secondSprite.
Стоит заметить, что в в случае если secondSprite будет удален со сцены и ссылки на него будут уничтожены, то сборщик мусора рано или поздно соберет и его и instanceLink, даже если instanceLink будет находиться в списке отображения secondSprite. Это произойдет потому, что secondSprite и instanceLink по сути являются мертвыми объектами так как ссылка на instanceLink содержится только в мертвом объекте, а следовательно она недействительна.
Но стоит избегать этой логики при программировании, так как garbage collector’у понадобится больше одной итерации для того, чтобы определить, что instanceLink готов к уничтожению, следовательно на операцию очистки потратится больше ресурсов и процессорного времени.
2.3 Слушатели событий
Все та же проблема ожидает вас при подписке на прослушивание событий объектов (addEventListener). Если вы подписались на событие и не удалите слушателя перед очисткой ссылок на объект, то после очистки объект оных объект так и останется в памяти и будет функционировать, так как имеется ссылка на него в виде подписки.
Избежать этого можно двумя путями:
- Использовать weakReference (мягкую ссылку) при подписке
object.addEventListener(type, listener, false, 0, true);
Мягкая ссылка означает, что в случае если сборщик мусора решит проверить можно ли удалить object, то данная подписка на событие не воспрепятствует его удалению.
- Самостоятельно удалив слушателя:
object.removeEventListener(type,listener);
Стоит избегать использования мягких ссылок там, где это не является поистине необходимым, так как сборщик мусора может уничтожить объект до того, как он выполнит свои обязанности.
Необходимо отметить что для экранных объектов не обязательно удалять прослушивание событий от мышки, при удалении ссылок, так как garbage collector самостоятельно «обрежет» эту связь, но опять же это отнимет больше ресурсов, нежели при ручной отписке от событий.
2.4 Мягкие ссылки
Помимо мягких ссылок в подписке на события, можно использовать их и в Dictionary, для этого при создании экземпляра Dictionary параметр weakKeys равным true.
var dict : Dictionary = new Dictionary(true);
Это означает, что ключи (!) dictionary будут использоваться в качестве мягких ссылок, а не жестких. То есть:
dict[instanceLink] = true;
Не заставит сборщик мусора отказаться от идеи удалить объект instanceLink из памяти, если других ссылок на него более не существует.
3. Итог
После использования объектов, для того чтобы они были удалены из памяти необходимо:
- Удалить всех слушателей объекта
- В случае если это экранный объект, удалить его из списка отображения
- Уничтожить все ссылки на него
Tags: as3, leaks, leaks as3, memory leaks, profiler, оптимизация, память, утечки

Как в магазин сходил…
Спасибо!!!
Спасибо.
короче гемор)