Пример утечки памяти Android из ввода-вывода Google

#android #memory-leaks

#Android #утечки памяти

Вопрос:

Я только что просмотрел видео Google io «Управление памятью для Android». Слайды доступны здесь http://dubroy.com/memory_management_for_android_apps.pdf . Пример утечки памяти приведен на слайде 36.

Я не понимаю, почему это вызывает утечку после изменения ориентации. Я понимаю, что утечка является внутренним классом и имеет ссылку на внешний класс. Кроме того, я понимаю, что статическая переменная «leak» ссылается на «Протекающий» объект .. таким образом, вся деятельность. Я думаю, что это особенное из-за ключевого слова static. Статические переменные имеют определенную память и, вероятно, не являются gc’ed (по крайней мере, до тех пор, пока работает приложение) ?!?

Ну, что происходит при изменении ориентации? Создается новый экземпляр activity и onCreate вызывается activities. leak == null равно false. Утечка по-прежнему указывает на «старую» активность. Это утечка. Старая активность не может быть восстановлена, верно?

Почему использование памяти увеличивается с каждым изменением ориентации? В моем (неправильном) понимании я бы предположил, что только первое действие не может быть выполнено. Другие действия, которые создаются из-за изменения ориентации, могут быть gc’ed, потому что на них не ссылается эта статическая переменная «leak».

Однако .. очевидно..Я совершенно не прав!

Комментарии:

1. Было ли это полезно? Принять было бы неплохо 🙂

2. Я думаю, вы думаете, что уничтожение активности == сбор мусора. Я добавил ответ, который пытается объяснить, что происходит. По сути, это потому, что утечка делает == null во вновь созданном действии. Почему, прочитайте мой ответ.

Ответ №1:

Классическое объяснение утечки памяти контекста изменения ориентации из блога Google. Я думаю, вы прошли большую часть пути, отметив статическую ссылку внутреннего на внешний класс.

Комментарии:

1. Да, я читал это раньше. На самом деле это то же самое, и автор говорит, что «он пропускает первое действие». Это поведение, которое я описал выше. Мне ясно, что первая активность протекает. Но только первый. Изменения ориентации после этого больше не должны влиять / увеличивать кучу, соответственно, больше не должно происходить утечек. Но в видео, которое я опубликовал, куча, похоже, увеличивается с каждым изменением ориентации (начинается с 28-й минуты) с 9 МБ до 12-15 МБ. Что ж, я собираюсь протестировать это в ближайшее время

2. Я понимаю, что каждый раз, когда вы меняете ориентацию, вы теряете активность, но она не получает GCd. Когда вы возвращаетесь к портретному режиму, переключившись на альбомную ориентацию, вы не получаете свой первоначальный контекст.

3. Да, вы не получаете свой первоначальный контекст. Но почему каждый раз? Статическая переменная ссылается только на первое действие

4. После первого создания действия статическая переменная всегда не равна нулю. Таким образом, статическая переменная всегда будет ссылаться на первое действие

Ответ №2:

Вы не понимаете, потому что допустили критическую ошибку. утечка == null имеет значение true во вновь созданном действии. утечка по-прежнему не указывает на «старую» активность.

Почему? Я думал, что утечка была статической, спросите вы. Ну . . .

Итак, в первый раз создается действие, утечка равна нулю, затем onCreate() и leak теперь ссылаются на протекающий объект. Если я создам больше экземпляров этого действия, их утечки не будут равны нулю и будут ссылаться на тот же объект.

Но то, что происходит, когда вы меняете ориентацию, заключается в том, что действие уничтожается. Итак, нет существующего экземпляра объекта activity. Затем Android создает новое действие, где утечка равна нулю (поскольку, насколько это касается Android, другого экземпляра действия не существует).

Однако для сборщика мусора кто-то содержит ссылку на уничтоженную активность, а именно на ее внутренний класс утечки. Таким образом, это не освободит эту память. Следовательно, по мере того, как вы продолжаете менять ориентацию, вы продолжаете пропускать память, занимаемую действиями.