Как Garbage Collector определяет мусорный объект

Ответ

Garbage Collector в Android (начиная с ART) использует алгоритм Mark-and-Sweep:

  1. Mark (Пометка)
    Проходит по всем достижимым объектам, начиная с GC Roots (активные потоки, статические поля, локальные переменные), и помечает их как живые.

  2. Sweep (Очистка)
    Удаляет все объекты, которые не были помечены (недостижимые).

Пример утечки памяти:

class LeakyActivity : Activity() {
    private val leak = SomeSingleton.getInstance(this) // Активность удерживается синглтоном
}

Нюансы:

  • Generational Collection – объекты делятся на молодые (часто удаляются) и старые (редко).
  • Concurrent GC – работает параллельно с приложением, минимизируя лаги.
  • Finalization – перед удалением вызывается finalize(), но это deprecated с API 28.

Для отладки утечек используйте LeakCanary или Android Profiler.

Ответ 18+ 🔞

А, слушай, про эту вашу сборку мусора в Андроиде! Ну, в общем, ёпта, история как в жизни. Представь себе бардак в комнате после вечеринки. Garbage Collector — это такой занудный уборщик, который приходит и наводит порядок по чёткому плану, а не просто машет шваброй.

Вот его план, бля, классический Mark-and-Sweep (Пометка и Очистка), как будто он не в телефоне, а в моей голове после вчерашнего:

  1. Mark (Пометка)
    Чувак начинает с главных зацепок — GC Roots. Это как его список VIP-персон, которых трогать нельзя: активные потоки, статические поля, локальные переменные в стеке. От них он идёт по всем связям и помечает каждый досягаемый объект как живого. Всё, что помечено — это типа «это моё, не выкидывать». Всё остальное — на выброс. Подозрение ебать чувствую, что тут можно накосячить.

  2. Sweep (Очистка)
    А вот тут начинается зачистка. Всё, что не помечено — пошло нахуй, в небытие. Память освобождена. Красота.

А теперь, я тебе покажу, где собака зарыта, точнее, где память начинает течь как решето. Вот тебе классический пиздец, пример утечки:

class LeakyActivity : Activity() {
    private val leak = SomeSingleton.getInstance(this) // Активность удерживается синглтоном
}

Смотри, в чём прикол: ты передаёшь ссылку на свою активность (this) в какой-то синглтон, который живёт вечно. Активность должна умереть, когда пользователь ушёл с экрана, но синглтон её держит за жопу и не отпускает. Сборщик мусора смотрит: объект вроде как достижим от вечного синглтона! Доверия ебать ноль к таким схемам. И вот она, утечка — активность висит в памяти мёртвым грузом, как хуй в пальто.

Ну и по мелочи, нюансы, бля:

  • Generational Collection – Умные ребята разделили объекты на молодых и старых. Молодые (создались недавно) умирают часто и быстро. Старые (пережили несколько сборок) — к ним реже подходят. Эффективность, мать её.
  • Concurrent GC – Самый важный для нас, пользователей. Эта штука старается работать параллельно с твоим приложением, чтобы не было этих ебучих лагов и фризов каждые пять секунд. Не идеально, но старается.
  • Finalization – Раньше, перед тем как удалить объект, могли вызвать его метод finalize(). Это была такая последняя просьба «ой, подожди, я ещё кое-что сделать хочу». Сейчас это deprecated с API 28. И правильно, да похуй на эти предсмертные хотелки, только тормозит всё.

А если у тебя в приложении волнение ебать и ты чувствуешь, что память уплывает — не гадай на кофейной гуще. Бери LeakCanary — эта библиотека орет, как резаная, когда видит утечку. Или ковыряйся в Android Profiler в студии. Без инструментов тут ни хуя себе не разберёшься.