Когда срабатывает Garbage Collector на разные ссылки в Java

Ответ

Garbage Collector (GC) в Java освобождает память, когда объект становится недостижимым (нет активных ссылок). Основные сценарии:

  1. Локальные переменные – после выхода из метода.
  2. Null-ссылки – присвоение null делает объект кандидатом на сборку.
  3. Переприсвоение ссылки – старая ссылка теряется.
  4. Изолированные объекты – циклические ссылки без внешних связей.

Пример:

void example() {
    Object obj1 = new Object(); // 1. Создаем объект
    Object obj2 = new Object(); // 2. Еще один объект
    obj1 = obj2; // 3. obj1 теперь ссылается на obj2, старый объект доступен для GC
    obj2 = null; // 4. obj2 = null, но obj1 еще держит ссылку
} // 5. После выхода из метода все локальные ссылки теряются – GC может собрать объекты

Важно: GC работает не мгновенно, а по мере необходимости или при нехватке памяти.

Ответ 18+ 🔞

Давай разберёмся с этим вашим сборщиком мусора, а то народ пугается, как будто это какой-то демон из ада. Вообще, штука полезная, но работает она по своим, иногда загадочным, правилам.

Представь, что твоя оперативка — это комната в общаге. Ты там живёшь, тусуешься, создаёшь объекты — new Object(). Это как притащить в комнату новый стул, гитару или бутылку пива. Пока ты на эту вещь смотришь (то есть есть на неё ссылка), она твоя. Стоит и стоит.

А теперь сценарии, когда эта хрень становится мусором и её можно выкинуть (собрать GC):

  1. Локальные переменные. Ты в методе void getDrunk() создал локальную переменную Beer b = new Beer("Baltica"). Выпил, вышел из метода — и всё, про эту бутылку ты забыл. Сборщик мусора, видя, что на неё никто не ссылается, её благополучно выносит на помойку. Ёпта, логично же.

  2. Null-ссылки. Была у тебя крутая ссылка на объект Girlfriend gf = new Girlfriend("Наташа"). Потом ты ей позвонил, она сказала "у нас нет будущего". Ты пишешь в коде gf = null;. Всё, Наташа официально стала кандидатом на удаление из памяти. Жестоко, но справедливо.

  3. Переприсвоение. Была у тебя ссылка car на старенькую "девятку". Потом ты разбогател и написал car = new Porsche();. На "девятку" больше нет ссылки. Она теперь не твоя, и её можно утилизировать. Старое железо — на свалку истории.

  4. Изолированные объекты (циклические ссылки). Вот это многих вводит в ступор. Смотри: есть два друга-алкаша, Вася и Петя. У Васи есть ссылка на Петю (vasya.friend = petya), а у Пети — на Васю (petya.friend = vasya). Они вдвоём в замкнутом цикле, но больше НИКТО в программе о них не знает. Они сидят в углу комнаты и бухают, но для внешнего мира их как бы нет. Ни хуя себе, да? Так вот, GC — он умный, он это видит. Поскольку на эту парочку нет ссылок извне, он их спокойно собирает обоих, несмотря на то, что они ссылаются друг на друга. Главное — отрезать от "корней" программы.

Смотри на этот пример, тут всё наглядно:

void example() {
    Object obj1 = new Object(); // 1. Создали первый стул в комнате
    Object obj2 = new Object(); // 2. Создали второй стул
    obj1 = obj2; // 3. Внимание! Теперь obj1 смотрит на второй стул. А на первый стул ссылок ВООБЩЕ НЕТ. Он уже мусор!
    obj2 = null; // 4. Обнулили ссылку на второй стул, но ведь obj1 всё ещё на него смотрит! Так что он пока жив.
} // 5. Выходим из метода. Все локальные переменные (obj1, obj2) уничтожаются. Теперь НИКТО не ссылается ни на первый стул (он уже давно мусор), ни на второй. Всё, оба можно выкидывать.

И главное, что нужно понять — терпения ноль ебать! GC не работает по щелчку пальцев. Он ленивая жопа. Он собирает мусор тогда, когда захочет: обычно когда память на исходе и нужно место для новых объектов. Ты можешь предложить ему поработать (System.gc()), но это всего лишь намёк, а не приказ. Он тебе в ответ: "Да похуй, соберу когда созрею".

Так что живи спокойно, создавай объекты, но просто знай — за тобой приберут. Не сразу, но приберут.