Как LeakCanary находит ссылку на уничтоженную Activity
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как LeakCanary определяет утекшую Activity
LeakCanary — это мощный инструмент для обнаружения утечек памяти в Android приложениях. Его основная задача — находить объекты (например, уничтоженные Activity), которые были удалены из памяти системы (GC), но остаются в памяти приложения из-за ошибочных ссылок. Механизм работы можно разделить на несколько ключевых этапов.
1. Принцип обнаружения утечек
LeakCanary не отслеживает каждый объект постоянно. Он использует стратегию отслеживания "подозрительных" объектов после их предполагаемого уничтожения. Для Activity это критически важно, поскольку они должны быть полностью уничтожены после закрытия.
2. Интеграция и инициализация
LeakCanary интегрируется в приложение через ContentProvider или прямой вызов в Application.onCreate(). Это позволяет инструменту начать работу как можно раньше, без явной инициализации в коде разработчика.
// Пример автоматической установки (в современных версиях)
// В манифесте добавляется специальный ContentProvider
class App : Application() {
override fun onCreate() {
super.onCreate()
// Или ручная инициализация, если автоматическая недоступна
if (LeakCanary.isInAnalyzerProcess(this)) {
return
}
LeakCanary.Config.config = ...
}
}
3. Механизм отслеживания уничтоженных Activity
Шаг 1: Регистрация Activity для наблюдения
Когда Activity достигает конца своего жизненного цикла (после onDestroy()), LeakCanary помещает ее в специальный хранилище слабых ссылок (WeakReference). Слабые ссылки не препятствуют сборке мусора: если объект Activity удаляется GC, ссылка автоматически становится null.
// Примерная логика внутри LeakCanary
RefWatcher refWatcher = LeakCanary.install(this);
activity.onDestroy() {
// После уничтожения Activity регистрируем ее для наблюдения
refWatcher.watch(activity, "ActivityDestroyed");
}
Шаг 2: Проверка после сборки мусора
LeakCanary периодически (или по определенным событиям) триггерит искусственную сборку мусора и проверяет слабые ссылки:
- Если ссылка стала
null— Activity успешно удалена, утечки нет. - Если ссылка не null — объект все еще в памяти, что указывает на возможную утечку.
Шаг 3: Анализ цепочки ссылок (Heap Dump)
Если утечка обнаружена, LeakCanary создает дамп heap памяти (Heap Dump) — полный снимок всех объектов в памяти приложения. Затем анализирует этот дамп с помощью библиотеки Shark (или ранее HAHA).
Анализ включает:
- Поиск "корня" утечки: Определение, какой объект держит "сильную" ссылку на уничтоженную Activity.
- Построение цепочки ссылок: От Activity до GC Root (например, статическое поле, поток, системный класс).
// Пример вывода анализа LeakCanary
Leak trace:
┬───
│ Static field: SomeSingleton.instance
│ ↓ instance
│ Class: SomeSingleton
│ ↓ someActivityReference
│ Class: DestroyedActivity // Уничтоженная Activity, но все еще в памяти!
4. Ключевые технические детали
- WeakReference и ReferenceQueue: LeakCanary использует их для эффективного отслеживания без вмешательства в работу GC.
- Периодические проверки: Проверки выполняются в фоновом потоке, чтобы не мешать основному UI.
- Детальный отчет: При обнаружении утечки выводится не только цепочка ссылок, но и рекомендации по исправлению (например, "Не забывайте очищать статические ссылки на Context").
5. Пример распространенной утечки Activity
Частая причина — сохранение ссылки на Activity в статическом поле или в сильном ссылочном поле другого долгоживущего объекта (например, Singleton).
// Проблемный код, вызывающий утечку
public class AppSingleton {
private static Context appContext; // Статическое поле
public void setContext(Context context) {
this.appContext = context; // Здесь может передаться Activity
}
}
// В Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppSingleton.getInstance().setContext(this); // Утечка!
}
LeakCanary обнаружит, что уничтоженная Activity остается в памяти через статическое поле AppSingleton.appContext.
Заключение
LeakCanary находит ссылки на уничтоженные Activity через комбинацию слабых ссылок, искусственного GC, дампа памяти и анализа цепочек ссылок. Это позволяет точно локализовать источник утечки и предоставить разработчику actionable информацию для исправления ошибки, значительно улучшая стабильность и производительность Android приложений.