Создайте дамп кучи, чтобы увидеть, какие объекты в вашем приложении используют память во время захвата, и выявить утечки памяти или поведение выделения памяти, которое приводит к зависаниям, зависаниям и даже сбоям приложения. Особенно полезно создавать дампы кучи после расширенного сеанса пользователя, когда они могут показать объекты, все еще находящиеся в памяти, которых там больше не должно быть.
На этой странице описаны инструменты, которые Android Studio предоставляет для сбора и анализа дампов кучи. Кроме того, вы можете проверить память вашего приложения из командной строки с помощью dumpsys
, а также просмотреть события сборки мусора (GC) в Logcat .
Почему вам следует профилировать память приложения
Android предоставляет среду управляемой памяти : когда Android определяет, что ваше приложение больше не использует некоторые объекты, сборщик мусора освобождает неиспользуемую память обратно в кучу. То, как Android находит неиспользуемую память, постоянно совершенствуется, но в какой-то момент во всех версиях Android система должна ненадолго приостановить ваш код. Большую часть времени паузы незаметны. Однако если ваше приложение выделяет память быстрее, чем система может ее собрать, ваше приложение может задерживаться, пока сборщик не освободит достаточно памяти для удовлетворения ваших выделений. Задержка может привести к тому, что ваше приложение пропустит кадры и станет заметной медлительностью.
Даже если ваше приложение не проявляет медлительности, если в нем происходит утечка памяти, оно может сохранить эту память, даже находясь в фоновом режиме. Такое поведение может замедлить остальную производительность памяти системы из-за ненужных событий сборки мусора. В конце концов, система вынуждена завершить процесс вашего приложения, чтобы освободить память. Затем, когда пользователь возвращается в ваше приложение, процесс приложения должен полностью перезапуститься.
Информацию о методах программирования, которые могут сократить использование памяти вашим приложением, можно найти в статье «Управление памятью вашего приложения» .
Обзор дампа кучи
Чтобы записать дамп кучи, выберите задачу «Анализ использования памяти (дамп кучи)» (используйте Profiler: запустите «приложение» как отлаживаемое (полные данные) ), чтобы записать дамп кучи. При сбросе кучи объем памяти Java может временно увеличиться. Это нормально, поскольку дамп кучи происходит в том же процессе, что и ваше приложение, и для сбора данных требуется некоторый объем памяти. После захвата дампа кучи вы увидите следующее:
В списке классов отображается следующая информация:
- Выделения : количество выделений в куче.
Собственный размер : общий объем собственной памяти, используемой этим типом объекта (в байтах). Здесь вы увидите память для некоторых объектов, выделенных в Java, поскольку Android использует собственную память для некоторых классов платформы, таких как
Bitmap
.Небольшой размер : общий объем памяти Java, используемый этим типом объекта (в байтах).
Сохраненный размер : общий размер памяти, сохраняемый всеми экземплярами этого класса (в байтах).
Используйте меню кучи для фильтрации по определенным кучам:
- Куча приложения (по умолчанию) : основная куча, в которой ваше приложение выделяет память.
- Куча изображений : образ загрузки системы, содержащий классы, предварительно загруженные во время загрузки. Выделения здесь никогда не перемещаются и не исчезают.
- Зиготная куча : куча копирования при записи, из которой в системе Android создается ответвление процесса приложения.
Используйте раскрывающийся список расположения, чтобы выбрать способ распределения:
- Упорядочить по классу (по умолчанию) : группирует все выделения по имени класса.
- Упорядочить по пакетам : группирует все выделения по имени пакета.
Используйте раскрывающийся список классов, чтобы отфильтровать группы классов:
- Все классы (по умолчанию) : отображаются все классы, включая классы из библиотек и зависимостей.
- Показать утечки активности/фрагментов : показывает классы, вызывающие утечки памяти.
- Показать классы проекта : отображаются только классы, определенные вашим проектом.
Щелкните имя класса, чтобы открыть панель «Экземпляр» . Каждый указанный экземпляр включает в себя следующее:
- Глубина : кратчайшее количество переходов от любого корня сборщика мусора до выбранного экземпляра.
- Собственный размер : размер этого экземпляра во встроенной памяти. Этот столбец виден только для Android 7.0 и выше.
- Мелкий размер : размер этого экземпляра в памяти Java.
- Сохраняемый размер : размер памяти, в которой доминирует этот экземпляр (согласно дереву доминаторов ).
Щелкните экземпляр, чтобы отобразить сведения об экземпляре , включая его поля и ссылки . Общие типы полей и ссылок являются структурированными типами. , массивы и примитивные типы данных на Яве. Щелкните правой кнопкой мыши поле или ссылку, чтобы перейти к соответствующему экземпляру или строке исходного кода.
- Поля : отображаются все поля в этом экземпляре.
- Ссылки : показывает каждую ссылку на объект, выделенный на вкладке «Экземпляр» .
Найдите утечки памяти
Чтобы быстро отфильтровать классы, которые могут быть связаны с утечками памяти, откройте раскрывающийся список классов и выберите « Показать утечки активности/фрагментов» . Android Studio показывает классы, которые, по ее мнению, указывают на утечки памяти для экземпляров Activity
и Fragment
в вашем приложении. Типы данных, отображаемые фильтром, включают следующее:
- Экземпляры
Activity
, которые были уничтожены, но на которые все еще ссылаются. - Экземпляры
Fragment
, у которых нет допустимогоFragmentManager
, но на которые все еще ссылаются.
Имейте в виду, что фильтр может давать ложные срабатывания в следующих ситуациях:
-
Fragment
создан, но еще не использован. -
Fragment
кэшируется, но не как частьFragmentTransaction
.
Чтобы искать утечки памяти вручную, просмотрите списки классов и экземпляров, чтобы найти объекты с большим Retained Size . Ищите утечки памяти, вызванные любой из следующих причин:
- Долгоживущие ссылки на
Activity
,Context
,View
,Drawable
и другие объекты, которые могут содержать ссылку на контейнерActivity
илиContext
. - Нестатические внутренние классы, такие как
Runnable
, которые могут содержать экземплярActivity
. - Тайники, в которых хранятся объекты дольше, чем необходимо.
При обнаружении потенциальных утечек памяти используйте вкладки «Поля» и «Ссылки» в разделе «Сведения об экземпляре» , чтобы перейти к интересующей строке экземпляра или исходного кода.
Вызов утечек памяти для тестирования
Чтобы проанализировать использование памяти, вам следует усилить код вашего приложения и попытаться вызвать утечки памяти. Один из способов спровоцировать утечку памяти в вашем приложении — дать ему поработать некоторое время, прежде чем проверять кучу. Утечки могут проникнуть в верхнюю часть кучи. Однако чем меньше утечка, тем дольше вам нужно запускать приложение, чтобы ее увидеть.
Вы также можете вызвать утечку памяти одним из следующих способов:
- Поворачивайте устройство из книжного положения в альбомное и обратно несколько раз, находясь в разных состояниях активности. Вращение устройства часто может привести к утечке из приложения объекта
Activity
,Context
илиView
, поскольку система воссоздаетActivity
, и если ваше приложение содержит ссылку на один из этих объектов где-то еще, система не сможет выполнить сборку мусора. - Переключайтесь между своим приложением и другим приложением, находясь в разных состояниях активности. Например, перейдите на главный экран, а затем вернитесь в приложение.
Экспорт и импорт записи дампа кучи
Вы можете экспортировать и импортировать файл дампа кучи на вкладке «Прошлые записи» в профилировщике. Android Studio сохраняет запись как файл .hprof
.
Альтернативно, чтобы использовать другой анализатор файлов .hprof
, например jhat , вам необходимо преобразовать файл .hprof
из формата Android в формат файла .hprof
Java SE. Чтобы преобразовать формат файла, используйте инструмент hprof-conv
, расположенный в каталоге {android_sdk}/platform-tools/
. Запустите команду hprof-conv
с двумя аргументами: исходное имя файла .hprof
и место для записи преобразованного файла .hprof
, включая новое имя файла .hprof
. Например:
hprof-conv heap-original.hprof heap-converted.hprof