Память и основы 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, а при поиске утечки анализируйте цепочку удерживающих ссылок.