Перейти к содержанию

Память и основы runtime

Стек и куча

Базовые знания о памяти и runtime помогают понимать время жизни объектов, сборку мусора, утечки и проблемы производительности из-за выделения памяти в Android-приложениях.

Управляемая память в Android

ART размещает Java- и Kotlin-объекты в управляемой куче процесса. Приложение также использует память вне этой кучи: стеки потоков, нативные выделения, код, графические буферы и отображённые в память файлы. GC освобождает управляемые объекты, но не все виды ресурсов и нативных выделений.

Стек и куча

У каждого потока есть стек вызовов с кадрами активных функций, служебными данными и некоторыми локальными значениями. Кадр удаляется после возврата из функции. Глубокая или бесконечная рекурсия может исчерпать стек и вызвать StackOverflowError.

Объекты обычно создаются в управляемой куче, а локальная переменная может хранить ссылку на объект. Модель «стек или куча» полезна, но точное размещение остаётся деталью реализации: ART может оптимизировать выделения. Если процесс не может выполнить новое выделение, возможен OutOfMemoryError, даже когда часть недостижимых объектов ещё не собрана.

Достижимость и сборка мусора

Сборщик начинает с корней GC, например активных потоков, статических полей и JNI-ссылок, и проходит по цепочкам ссылок. Управляемый объект становится кандидатом на сборку, когда он больше недостижим, а не просто перестал быть нужен приложению. Цикл объектов можно собрать, если к нему нет пути от корня.

Поэтому утечка памяти обычно является ошибкой времени жизни: объект всё ещё достижим, но уже не нужен. Типичные примеры в Android - singleton, удерживающий Activity, не удалённый listener или callback операции, переживший экран. Момент запуска GC не гарантирован; для освобождения ресурсов следует использовать lifecycle API или Closeable, а не финализацию.

Сильные, мягкие, слабые и фантомные ссылки

  • Сильная ссылка - обычная ссылка, которая сохраняет объект достижимым.
  • Слабая ссылка не удерживает объект от сборки. Она может быть полезна во вспомогательных отображениях, но не заменяет явное удаление listener и корректное владение по lifecycle.
  • Мягкая ссылка может сохраняться до усиления давления на память. Политика её очистки непредсказуема, поэтому для кешей Android обычно лучше задавать явный предел размера, например через LruCache.
  • Фантомная ссылка вместе с ReferenceQueue применяется для низкоуровневой обработки после потери достижимости объекта. Прикладному коду она нужна редко; Cleaner или явное владение ресурсом обычно понятнее.

Частые временные выделения могут увеличить нагрузку на GC и привести к рывкам интерфейса. Оптимизируйте после измерений в Android Studio или Perfetto, а при поиске утечки анализируйте цепочку удерживающих ссылок.

Связанные темы