← Назад к вопросам

Как понять что в Dump есть утечка памяти

2.3 Middle🔥 122 комментариев
#JVM и память

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Определение утечек памяти с помощью Dump (Heap Dump)

Heap Dump — это снимок памяти приложения на определенный момент времени, содержащий информацию обо всех объектах в heap, их размерах, ссылках и цепочках достижимости. В Android анализ Dump выполняется для выявления утечек памяти — ситуаций, когда объекты, более не нужные приложению, не освобождаются сборщиком мусора (Garbage Collector, GC), что приводит к росту потребления памяти и потенциальным падениям из-за OutOfMemoryError.

Ключевые признаки утечки в Heap Dump

Чтобы понять, есть ли утечка, нужно искать следующие паттерны:

  1. Необоснованный рост числа объектов одного типа (особенно Activity, Fragment, View, Context) при многократных операциях (например, открытие/закрытие экрана).
  2. Цепочки достижимости (Retaining Path), которые удерживают объекты от сборки мусора через ссылки от корневых объектов (Roots), таких как статические поля, потоки (Threads) или системные контексты.
  3. Дублирующиеся объекты, которые должны быть единственными (например, синглтоны), но присутствуют в нескольких экземплярах.
  4. Большие объекты (например, Bitmap, массивы), которые не освобождаются после использования.

Практический анализ с помощью Android Studio Profiler

Android Studio предоставляет инструменты для захвата и анализа Dump. Вот пошаговый подход:

  1. Захватите Heap Dump во время воспроизведения сценария, подозрительного на утечку (например, после 5-10 открытий/закрытий Activity).

  2. Фильтрация по классам: в открывшемся Dump отфильтруйте объекты по ключевым классам, например:

    • Activity
    • Fragment
    • Ваши кастомные классы (например, MyPresenter)
  3. Проверьте количество экземпляров (Instance Count). Если для Activity вы видите более 1-2 экземпляров при одном открытом экране — это индикатор утечки.

// Пример кода, вызывающего утечку через статическую ссылку:
public class LeakySingleton {
    private static Context sContext; // Статическое поле удерживает Context

    public static void setContext(Context context) {
        sContext = context; // Утечка: Activity не сможет быть очищена
    }
}
  1. Изучите Retaining Path: для каждого подозрительного объекта нажмите на него и просмотрите цепочку ссылок от корней (Roots). Ищите:
    • Статические поля (static fields)
    • Внутренние классы с неявными ссылками на внешние (non-static inner classes)
    • Регистрации в слушателях (Listeners), которые не отменяются
// Пример утечки через слушатель в Android:
class MyActivity : AppCompatActivity() {
    private val listener = object : SomeListener {
        override fun onEvent() {
            // Этот анонимный класс неявно ссылается на MyActivity
            doSomething()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        SomeManager.registerListener(listener) // Регистрация
        // Если не вызвать unregisterListener, Activity останется в памяти
    }
}

Инструменты и методы анализа

  • Android Studio Memory Profiler: основной инструмент для визуального анализа.
  • LeakCanary: автоматическая детекция утечек в продакшене. Он создает Dump при подозрении на утечку и показывает понятный стек.
  • MAT (Eclipse Memory Analyzer) или YourKit: более продвинутые инструменты для детального анализа сложных случаев.

Пример вывода LeakCanary

LeakCanary генерирует отчет, который прямо указывает на утечку:

┬───
│ GC Root: Static field com.example.LeakySingleton.sContext
│
├─ com.example.LeakySingleton instance
│    Leaking: YES (ObjectWatcher was watching this)
│    ↓ LeakySingleton.sContext
│                     ~~~~~~~~
╰→ com.example.MyActivity instance
     Leaking: YES (Activity#mDestroyed is true)

Вывод: статическое поле sContext удерживает MyActivity, которая уже уничтожена (mDestroyed = true), что является явной утечкой.

Профилактика утечек

  • Избегайте статических ссылок на Context или View.
  • Используйте слабые ссылки (WeakReference) при необходимости.
  • Отменяйте регистрацию слушателей в onDestroy() или с помощью LifecycleObserver.
  • Для долгих операций используйте ViewModel или CoroutineScope, привязанные к жизненному циклу.

Анализ Heap Dump требует практики, но систематический поиск избыточных экземпляров и их цепочек достижимости — надежный метод выявления утечек. Интеграция LeakCanary значительно упрощает этот процесс в разработке.

Как понять что в Dump есть утечка памяти | PrepBro