OutOfMemoryError. Боремся с утечками памяти в Android +16


В данной заметке мы рассмотрим несколько примеров утечек памяти в Android приложении. Также мы рассмотрим исправления этих утечек. Я хочу показать, что с утечками памяти можно и нужно бороться. Я не буду рассказывать про инструменты для анализа памяти, только лишь приведу ссылки на самые важные из них.

Неправильный AnimationListener


Для привлечения внимания к новому функционалу было принято решение воспользоваться анимацией. Необходимо было показать на короткий период View с подсказкой. Пример можно увидеть на изображении ниже:

Гифка с примером


Позже обнаружилась утечка Activity.



Проблема заключалась в том, что анимация fadeOut использовала слушателя от анимации fadeIn, что приводило к бесконечному запуску анимации fadeOut.



Исправить это было достаточно легко.



Анимации часто являются причинами утечек. Этого очень легко достигнуть забыв остановить бесконечную анимацию или запустив анимацию на неоправданно длительное время.

android.widget.Editor$Blink


Бывает утечки памяти находятся и в самой платформе. Однажды я получил такой отчет:



Чтобы воспроизвести утечку достаточно создать Dialog с EditText внутри и что-нибудь в нем напечатать.

Гифка с примером


Как оказалось, это известный баг и он уже исправлен. Там же можно найти хак, для исправления этой утечки:



Утечка от производителя. Singleton — зло


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



На этот раз мне опять повезло и я нашел готовое решение в сети (1, 2).



Результаты




В результате количество OutOfMemoryError уменьшилось почти в 7 раз. Так же уменьшилось количество RuntimeException,InflateException: часть из них — это пойманные и обернутые OutOfMemoryError. Одним из ограничивающих факторов в исправлении такого рода ошибок является то, что я не могу делать обновления, которые не содержат внешних изменений (для пользователей выглядит как “Пустое обновление”) В таких случаях приходится ждать реализации нового функционала для проверки результатов.

Выводы


  • Документируйте не тривиальные/не очевидные моменты в коде, которые исправляют утечки памяти. Часто они выглядят подозрительно.
  • Не ошибается тот, кто ничего не делает. Иногда приходится фиксить утечки памяти в чужом коде.
  • Нужно знать свой инструментарий (hprof-conv, VisualVM, OQL, leakcanary)
  • Обязательно делайте измерения и следите за ними(crash-report tools).
  • Не допускайте увеличения количества ошибок.

Ссылки





К сожалению, не доступен сервер mySQL