GC Roots: почему Java не удаляет объект, которым мы больше не пользуемся



В прошлом посте разобрали важный момент:
-Xmx2g ограничивает Heap, но память JVM не заканчивается на Heap.

Теперь разберёмся, как JVM вообще решает, какие объекты можно удалить.

Представим:

public void process() {
User user = new User("Alex");
}

Метод завершился, переменная user больше не существует и кажется, объект можно удалить, и действительно — если на User больше никто не ссылается, GC сможет его собрать.

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

Если упрощённо JVM начинает поиск с особых объектов — GC Roots:

GC Roots
│
├── локальные переменные активных методов
├── статические поля
├── активные Java-потоки
└── другие специальные ссылки JVM
│
↓
Object A
│
↓
Object B

Если до объекта можно добраться от GC Root — объект считается живым.
Если добраться нельзя — объект становится кандидатом на сборку.

Но теперь интересное.))
Представим:

public static List<User> users = new ArrayList<>();

И где-то в коде:
users.add(new User("Alex"));

Через неделю этот пользователь нам уже вообще не нужен, однако его забыли удалить из списка.

Что происходит?
GC Root
↓
static users
↓
ArrayList
↓
User

Объект всё ещё достижим и для GC он жив.
Тут совершенно неважно, что бизнес-логике этот User больше не нужен.

Если продолжать добавлять объекты:
users.add(...)
users.add(...)
users.add(...)
...
коллекция будет расти.
И в какой-то момент мы получаем: OutOfMemoryError
Это один из классических вариантов memory leak в Java.

И здесь важный нюанс:
Memory leak в Java — это не обязательно потерянная память.

Часто это память, которую GC технически может освободить, но не имеет права, потому что объект всё ещё достижим.

Поэтому при расследовании проблем с памятью недостаточно смотреть:

"У нас много объектов"
Нужно задать другой вопрос:

«Почему эти объекты всё ещё достижимы от GC Roots?»

Именно поэтому при анализе Heap Dump мы ищем не только самые большие объекты, но и цепочку их удержания — Path to GC Roots.

И вот здесь JVM становится действительно интересной:
иногда проблема не в том, что приложение создаёт слишком много объектов.

Проблема в том, что оно слишком хорошо умеет их не удалять.
Просмотры: 40
Открыть в MAX Сообщить о неточности

Репосты публикации

Публикация канала

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти