Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Java: reachability, gc, roots

Как определяется достижимость объекта при сборке мусора?

Этот вопрос проверяет понимание базового принципа работы GC: почему один объект удаляется, а другой остается, и как ссылки образуют «живой граф» объектов.

Короткий ответ

Объект считается достижимым, если до него можно добраться по цепочке ссылок от GC Roots.
GC начинает обход от корней и помечает все найденные объекты как живые.
Если объект не помечен, значит до него нельзя добраться из работающей программы.
Такие объекты считаются мусором и могут быть удалены.

Длинный ответ

GC определяет, какие объекты можно удалить, используя концепцию достижимости: в памяти рассматривается граф объектов, соединенных ссылками.

Определение достижимости

Достижимость объекта — это возможность попасть к нему по цепочке ссылок, начиная от GC Roots.

Идея простая:

  1. Есть стартовые точки — GC Roots

  2. От них GC проходит по ссылкам

  3. Все посещенные объекты считаются живыми

  4. Непосещенные — кандидаты на удаление

Что считается GC Roots

GC Roots — это ссылки, которые «принадлежат» работающей программе и считаются всегда живыми:

  1. Локальные переменные и параметры методов в stack каждого потока

  2. Активные объекты потоков (Thread)

  3. Статические поля (static) загруженных классов

  4. Ссылки из нативного кода (JNI), если они закреплены как корни

Как GC реально находит живые объекты

На уровне идеи это выглядит как «обход графа»:

  1. GC собирает список GC Roots

  2. Помечает объекты, на которые они указывают

  3. Из каждого помеченного объекта идет дальше по ссылкам на другие объекты

  4. Пока есть новые найденные объекты — продолжает обход

После этого:

  1. Все помеченные объекты считаются живыми

  2. Все остальные — мусор

Пример на бытовом уровне

Представь, что:

  1. GC Roots — это «руки программы» (локальные переменные, статические поля)

  2. Ссылки — это «веревочки» между объектами

  3. Если от рук можно дотянуться до объекта по веревочкам — объект живой

  4. Если нет — его можно убрать

Важные нюансы, которые часто путают

1) Циклические ссылки не спасают объект

Если два объекта ссылаются друг на друга, но на них нет ссылок от GC Roots, они оба будут удалены.

Пример:

class Node { Node next; }

Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a;

a = null; // потеряли корневую ссылку
b = null; // теперь оба недостижимы

Цикл есть, но достижимости от корней нет — значит, мусор.

2) «Есть ссылка где-то» не означает «объект живой»

Имеет значение не факт существования ссылок, а наличие пути от GC Roots.

Например, если объект лежит в коллекции, но сама коллекция больше не достижима, то и объект тоже недостижим.

3) Статические поля легко удерживают объекты в памяти

Если положить объект в static поле, он становится достижимым от GC Roots через класс, и GC не сможет его удалить, пока класс загружен.

Пример:

public class CacheHolder {
    static final List<byte[]> cache = new ArrayList<>();
}

Если cache растет бесконтрольно — это типичный путь к утечке памяти.

Как это связано с утечками памяти в Java

В Java утечка чаще всего означает не «память потерялась», а то, что:

  1. Объекты больше не нужны

  2. Но они все еще достижимы от GC Roots

  3. Значит GC не имеет права их удалять

Типовые причины:

  1. Долгоживущие коллекции (кэш без ограничений)

  2. static ссылки на тяжелые объекты

  3. Подписки/листенеры, которые не отписали

  4. ThreadLocal, где значение не очистили

Краткий вывод

Достижимость определяется путём от GC Roots по цепочке ссылок.
Если путь есть — объект живой, если нет — GC может его удалить.
Чтобы избегать утечек, важно контролировать долгоживущие ссылки: static, коллекции, подписки и ThreadLocal.

Уровень

  • Рейтинг:

    5

  • Сложность:

    7

Навыки

  • Java

    Java

Ключевые слова

#reachability

#gc

#roots

Подпишись на Java Developer в телеграм