В этом документе предполагается, что вы следовали рекомендациям по управлению памятью для приложений Android, например, «Управление памятью вашего приложения» .
Введение
Утечка памяти — это тип утечки ресурсов, которая происходит, когда компьютерная программа не освобождает выделенную память, которая больше не нужна. Утечка может привести к тому, что приложение запросит больше памяти у ОС, чем доступно, и, таким образом, приведет к сбою приложения. Ряд неправильных практик может вызвать утечки памяти в приложениях Android, например, неправильное удаление ресурсов или неотмена регистрации слушателей, когда они больше не нужны.
Этот документ предоставляет вам некоторые передовые методы, которые помогут предотвратить, обнаружить и устранить утечки памяти в вашем коде. Если вы попробовали методы, описанные в этом документе, и подозреваете утечку памяти в наших SDK, см . Как сообщить о проблемах с Google SDK .
Прежде чем обратиться в службу поддержки
Прежде чем сообщать об утечке памяти в службу поддержки Google, следуйте рекомендациям и шагам отладки, приведенным в этом документе, чтобы убедиться, что ошибка не в вашем коде. Эти шаги могут решить вашу проблему, а если нет, они генерируют информацию, необходимую службе поддержки Google, чтобы помочь вам.
Предотвращение утечек памяти
Следуйте этим рекомендациям, чтобы избежать некоторых наиболее распространенных причин утечек памяти в коде, использующем Google SDK.
Лучшие практики для приложений Android
Убедитесь, что вы выполнили все следующие действия в своем приложении для Android:
- Освободите неиспользуемые ресурсы .
- Отмените регистрацию слушателей, если они больше не нужны .
- Отменяйте задачи, если они не нужны .
- Методы жизненного цикла вперед для высвобождения ресурсов .
- Используйте последние версии SDK
Подробную информацию по каждому из этих методов см. в следующих разделах.
Освобождение неиспользуемых ресурсов
Когда ваше приложение Android использует ресурс, обязательно освободите ресурс, когда он больше не нужен. Если вы этого не сделаете, ресурс продолжит занимать память даже после того, как ваше приложение закончит с ним работать. Для получения дополнительной информации ознакомьтесь с разделом Жизненный цикл активности в документации Android.
Освободить устаревшие ссылки GoogleMap в GeoSDK
Распространенной ошибкой является то, что GoogleMap может вызвать утечку памяти, если кэшируется с помощью NavigationView или MapView. GoogleMap имеет отношение 1 к 1 с NavigationView или MapView, из которого он извлекается. Вы должны либо убедиться, что GoogleMap не кэшируется, либо что ссылка освобождается при вызове NavigationView#onDestroy или MapView#onDestroy. Если вы используете NavigationSupportFragment, MapSupportFragment или ваш собственный фрагмент, оборачивающий эти представления, то ссылка должна быть освобождена в Fragment#onDestroyView.
class NavFragment : SupportNavigationFragment() {
var googleMap: GoogleMap?
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?,
): View {
super.onCreateView(inflater,parent,savedInstanceState)
getMapAsync{map -> googleMap = map}
}
override fun onDestroyView() {
googleMap = null
}
}
Отмените регистрацию слушателей, когда они больше не нужны
Когда ваше приложение Android регистрирует слушателя для события, например, нажатия кнопки или изменения состояния представления, обязательно отмените регистрацию слушателя, когда приложению больше не нужно отслеживать событие. Если вы этого не сделаете, слушатели продолжат занимать память даже после того, как ваше приложение закончит с ними.
Например, предположим, что ваше приложение использует Navigation SDK и вызывает следующий прослушиватель для прослушивания событий прибытия: метод addArrivalListener
для прослушивания событий прибытия, он также должен вызывать removeArrivalListener
, когда ему больше не нужно отслеживать события прибытия.
var arrivalListener: Navigator.ArrivalListener? = null
fun registerNavigationListeners() {
arrivalListener =
Navigator.ArrivalListener {
...
}
navigator.addArrivalListener(arrivalListener)
}
override fun onDestroy() {
navView.onDestroy()
if (arrivalListener != null) {
navigator.removeArrivalListener(arrivalListener)
}
...
super.onDestroy()
}
Отменяйте задачи, когда они не нужны
Когда приложение Android запускает асинхронную задачу, например загрузку или сетевой запрос, обязательно отмените задачу после ее завершения. Если задача не отменена, она продолжает работать в фоновом режиме даже после того, как приложение завершило ее.
Более подробную информацию о передовых методах см. в разделе Управление памятью приложения в документации Android.
Методы жизненного цикла вперед для высвобождения ресурсов
Если ваше приложение использует Navigation или Maps SDK, обязательно освободите ресурсы, перенаправив методы жизненного цикла (выделены жирным шрифтом) в navView
. Вы можете сделать это с помощью NavigationView
в Navigation SDK или MapView
в Maps или Navigation SDK. Вы также можете использовать SupportNavigationFragment
или SupportMapFragment
вместо прямого использования NavigationView
и MapView
соответственно. Фрагменты поддержки обрабатывают перенаправление методов жизненного цикла.
class NavViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
navView = ...
navView.onCreate(savedInstanceState)
...
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
navView.onSaveInstanceState(savedInstanceState)
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
navView.onTrimMemory(level)
}
/* Same with
override fun onStart()
override fun onResume()
override fun onPause()
override fun onConfigurationChanged(...)
override fun onStop()
override fun onDestroy()
*/
}
Используйте последние версии SDK
Google SDK постоянно обновляются новыми функциями, исправлениями ошибок и улучшениями производительности. Поддерживайте SDK в вашем приложении в актуальном состоянии, чтобы получать эти исправления.
Отладка утечек памяти
Если после реализации всех применимых рекомендаций, приведенных ранее в этом документе, утечки памяти все еще наблюдаются, выполните следующую процедуру отладки.
Прежде чем начать , вы должны быть знакомы с тем, как Android управляет памятью. Для получения информации прочтите Обзор управления памятью Android.
Для устранения утечек памяти выполните следующие действия:
- Воссоздайте проблему . Этот шаг необходим для ее отладки.
- Проверьте, соответствует ли ожидаемому использованию памяти . Убедитесь, что повышенное использование, которое кажется утечкой, на самом деле не является памятью, необходимой для работы вашего приложения.
- Отладка на высоком уровне . Существует несколько утилит, которые можно использовать для отладки. Три различных стандартных набора инструментов помогают отлаживать проблемы с памятью в Android: Android Studio, Perfetto и утилиты командной строки Android Debug Bridge (adb).
- Проверьте использование памяти вашим приложением . Получите дамп кучи и отслеживание распределения, а затем проанализируйте его.
- Устранение утечек памяти .
В следующих разделах эти шаги рассматриваются подробно.
Шаг 1: Воссоздайте проблему
Если вам не удалось воссоздать проблему, сначала рассмотрите сценарии, которые могут привести к утечке памяти. Прямой переход к просмотру дампа кучи может сработать, если вы знаете, что проблема была воссоздана. Однако, если вы просто получаете дамп кучи при запуске приложения или в другой случайный момент времени, то вы, возможно, не активировали условия для запуска утечки. Рассмотрите возможность проработки различных сценариев при попытке воссоздать проблему:
Какой набор функций активирован?
Какая конкретная последовательность действий пользователя приводит к утечке?
- Пробовали ли вы несколько итераций активации этой последовательности?
Какие состояния жизненного цикла прошло приложение?
- Пробовали ли вы несколько итераций через различные состояния жизненного цикла?
Убедитесь, что вы можете воссоздать проблему в последней версии SDK. Проблема из предыдущей версии могла быть уже исправлена.
Шаг 2: Проверьте, соответствует ли использование памяти приложением ожидаемому
Каждая функция требует дополнительной памяти. При отладке различных сценариев подумайте, можно ли ожидать, что это будет использование или это действительно утечка памяти. Например, для различных функций или пользовательских задач рассмотрите следующие возможности:
Вероятная утечка: активация сценария посредством нескольких итераций приводит к увеличению использования памяти с течением времени.
Вероятное ожидаемое использование памяти : память восстанавливается после остановки сценария.
Возможное ожидаемое использование памяти : Использование памяти увеличивается в течение некоторого периода времени, а затем снижается. Это может быть связано с ограниченным кэшем или другим ожидаемым использованием памяти.
Если поведение приложения, скорее всего, связано с ожидаемым использованием памяти, проблему можно решить, управляя памятью вашего приложения. Для получения справки см. Управление памятью вашего приложения .
Шаг 3: Отладка на высоком уровне
Когда вы отлаживаете утечку памяти, начните с высокого уровня, а затем углубляйтесь, как только сузите круг возможностей. Используйте один из этих инструментов отладки высокого уровня, чтобы сначала проанализировать, есть ли утечка с течением времени:
Профилировщик памяти Android Studio (рекомендуется)
Профилировщик памяти Android Studio
Этот инструмент дает визуальную гистограмму потребляемой памяти. Дампы кучи и отслеживание выделения памяти также могут быть запущены из этого же интерфейса. Этот инструмент является рекомендацией по умолчанию. Для получения дополнительной информации см. Android Studio Memory Profiler .
Счетчики памяти Perfetto
Perfetto дает вам точный контроль над отслеживанием нескольких метрик и представляет все это в одной гистограмме. Для получения дополнительной информации см. Счетчики памяти Perfetto .
Утилиты командной строки Android debug bridge (adb)
Многое из того, что вы можете отслеживать с помощью Perfetto, также доступно в виде утилиты командной строки adb
, которую вы можете запросить напрямую. Вот несколько важных примеров:
Meminfo позволяет просматривать подробную информацию о памяти на определенный момент времени.
Procstats предоставляет важную обобщенную статистику с течением времени.
Важнейшей статистикой, на которую следует обратить внимание, является максимальный объем физической памяти (maxRSS), который требуется приложению с течением времени. MaxPSS может быть не таким точным. Чтобы узнать, как повысить точность, см. флаг adb shell dumpsys procstats --help –start-testing
.
Отслеживание распределения
Отслеживание распределения определяет трассировку стека, где была выделена память и не была ли она освобождена. Этот шаг особенно полезен при отслеживании утечек в машинном коде. Поскольку этот инструмент определяет трассировку стека, он может быть отличным средством для быстрой отладки основной причины или выяснения того, как воссоздать проблему. Для шагов по использованию отслеживания распределения см. Отладка памяти в машинном коде с отслеживанием распределения .
Шаг 4: Проверьте использование памяти вашим приложением с помощью дампа кучи
Один из способов обнаружить утечку памяти — получить дамп кучи вашего приложения и затем проверить его на наличие утечек. Дамп кучи — это снимок всех объектов в памяти приложения. Его можно использовать для диагностики утечек памяти и других проблем, связанных с памятью.
Android Studio может обнаруживать утечки памяти, которые не исправляются GC. Когда вы захватываете дамп кучи, Android Studio проверяет, есть ли активность или фрагмент, которые все еще доступны, но уже уничтожены.
- Захватите дамп кучи .
- Проанализируйте дамп кучи, чтобы найти утечки памяти .
- Устранение утечек памяти .
Подробную информацию смотрите в следующих разделах.
Захват кучи дампа
Чтобы захватить дамп кучи, можно использовать Android Debug Bridge (adb) или Android Studio Memory Profiler.
Используйте adb для захвата дампа кучи
Чтобы создать дамп кучи с помощью adb , выполните следующие действия:
- Подключите Android-устройство к компьютеру.
- Откройте командную строку и перейдите в каталог, где находятся инструменты adb.
Чтобы захватить дамп кучи, выполните следующую команду:
adb shell am dumpheap my.app.name $PHONE_FILE_OUT
Чтобы получить дамп кучи, выполните следующую команду:
adb pull $PHONE_FILE_OUT $LOCAL_FILE.
Используйте Android Studio для создания дампа кучи
Чтобы захватить дамп кучи с помощью Android Studio Memory Profiler, выполните следующие действия в разделе «Захват дампа кучи в Android».
Проанализируйте дамп кучи, чтобы найти утечки памяти.
После того, как вы захватили дамп кучи, вы можете использовать Android Studio Memory Profiler для его анализа. Для этого выполните следующие действия:
Откройте свой Android-проект в Android Studio.
Выберите «Выполнить» , а затем выберите конфигурацию «Отладка» .
Откройте вкладку Android Profiler .
Выберите Память .
Выберите Open heap dump и выберите файл дампа кучи, который вы сгенерировали. Профилировщик памяти отображает график использования памяти вашим приложением.
Используйте график для анализа дампа кучи:
Определите объекты, которые больше не используются.
Определите объекты, использующие большой объем памяти.
Посмотрите, сколько памяти использует каждый объект.
Используйте эту информацию, чтобы сузить круг возможных причин утечки памяти или найти ее и устранить.
Шаг 5: Устранение утечек памяти
После того, как вы определили источник утечки памяти, вы можете исправить это. Устранение утечек памяти в ваших приложениях Android помогает улучшить производительность и стабильность ваших приложений. В зависимости от сценария детали могут различаться. Тем не менее, следующие предложения могут помочь:
Убедитесь, что ваше приложение выделяет и освобождает память в соответствии с рекомендациями в разделе Android Управление памятью вашего приложения .
Удалите неиспользуемый код или ресурсы из вашего приложения. Подробности для приложений Android см. в разделе Лучшие практики для приложений Android .
Другие инструменты отладки
Если после выполнения этих шагов вы все еще не нашли и не устранили утечку памяти, попробуйте следующие инструменты:
- Отладка памяти в машинном коде с отслеживанием выделения памяти .
- Выявляйте утечки с помощью LeakCanary .
Отладка памяти в машинном коде с отслеживанием выделения памяти
Даже если вы не используете напрямую собственный код, несколько распространенных библиотек Android используют его, включая Google SDK. Если вы считаете, что утечка памяти находится в собственном коде, то есть несколько инструментов, которые вы можете использовать для ее отладки. Отслеживание распределения с помощью Android Studio или heapprofd (также совместимого с Perfetto) — отличный способ определить потенциальные причины утечки памяти и часто самый быстрый способ отладки.
Отслеживание распределения также имеет явное преимущество, поскольку позволяет вам делиться результатами, не включая конфиденциальную информацию, которую можно найти в куче.
Определите утечки с помощью LeakCanary
LeakCanary — мощный инструмент для выявления утечек памяти в приложениях Android. Чтобы узнать больше о том, как использовать LeakCanary в вашем приложении, посетите LeakCanary .
Как сообщить о проблемах с Google SDK
Если вы попробовали методы, описанные в этом документе, и подозреваете утечку памяти в наших SDK, обратитесь в службу поддержки клиентов, предоставив как можно больше следующей информации:
Действия по воссозданию утечки памяти . Если действия требуют сложного кодирования, может помочь копирование кода, который воспроизводит проблему, в наш пример приложения и предоставление дополнительных действий, которые необходимо выполнить в пользовательском интерфейсе для запуска утечки.
Дампы кучи, полученные из вашего приложения с воссозданной проблемой . Захватите дампы кучи в двух разных точках времени, которые показывают, что использование памяти значительно увеличилось.
Если ожидается утечка собственной памяти , поделитесь выводом отслеживания выделения из heapprofd .
Отчет об ошибке, созданный после того, как вы воссоздали условия утечки.
Трассировка стека любых сбоев, связанных с памятью .
Важное примечание : трассировки стека обычно недостаточны для устранения неполадок с памятью, поэтому обязательно предоставьте и другие формы информации.