С какой областью памяти работает Garbage Collector

Ответ

Garbage Collector (GC) в Android работает с кучей (Heap) — областью памяти, где хранятся объекты, созданные во время выполнения приложения. Он автоматически освобождает память, удаляя объекты, на которые нет активных ссылок.

Особенности:

  • Young Generation (Eden, Survivor spaces) — для краткоживущих объектов.
  • Old Generation — для долгоживущих объектов.
  • Permanent Generation (до Android 5.0) — метаданные классов (заменена на ART с компактирующим GC).

Пример утечки:

class LeakyActivity : Activity() {
    private val leak = staticList // Статическое поле держит ссылку на Activity
    companion object {
        val staticList = mutableListOf<Any>()
    }
}

Решение: избегать статических ссылок на контекст/View.

Ответ 18+ 🔞

Давай разберёмся с этим мусорщиком, а то у некоторых он в голове, а тут в андроиде. Ну, Garbage Collector, он же GC — это такой дворник в твоей оперативке. Сидит себе, курит, а как видит, что какой-то объект болтается без дела, на который никто не ссылается, — ёпта, сразу в мусорку его. Место освобождает. Всё происходит в куче (Heap) — это типа общага, где все твои объекты живут.

Как он там хозяйничает:

  • Молодёжь (Young Generation: Eden, Survivor spaces) — сюда попадают все новобранцы, объекты-однодневки. Пожили чуток, если никому не пригодились — в пизду, на выход. Выжившие переезжают.
  • Старики (Old Generation) — сюда попадают те, кто зацепился, выжил. Живут долго, но если и тут на них все забили — пизда рулю, и их убирают.
  • Постоянное поколение (Permanent Generation, но это старьё) — раньше тут метаданные классов лежали. Сейчас, ядрана вошь, в ART всё по-другому, с компактирующим сборщиком, чтобы память фрагментирована не была.

А теперь главный прикол, где все и обламываются. Смотри, классическая утечка, доверия ебать ноль к таким кодерам:

class LeakyActivity : Activity() {
    private val leak = staticList // Вот эта хуйня! Статик поле держит ссылку на всю Activity!
    companion object {
        val staticList = mutableListOf<Any>() // И этот список живёт вечно!
    }
}

Что происходит? Активность должна умереть, но статический список staticList — он же живёт, пока живёт класс. А в нём ссылка на leak, который ссылается на внешний класс LeakyActivity. И получается, что на твою активность есть живая, неубиваемая ссылка из статического контекста. Сборщик мусора подходит, смотрит — а, хуй с горы, ссылка есть, не трогаю. И память не освобождается. Активность накрылась медным тазом, но в памяти висит мёртвым грузом.

Решение, блядь, проще некуда: не пихай статические ссылки на контекст, вьюхи или сами активности. Вообще. Если очень надо — используй слабые ссылки (WeakReference), но лучше архитектуру пересмотреть. А то потом приложение жрёт память как не в себя, а ты гадаешь, какого хуя.