Возникают ли утечки памяти из-за retain cycle (цикла сильных ссылок) в средах с автоматическим сборщиком мусора (Garbage Collector)?

«Возникают ли утечки памяти из-за retain cycle (цикла сильных ссылок) в средах с автоматическим сборщиком мусора (Garbage Collector)?» — вопрос из категории Управление памятью, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, классические утечки памяти из-за retain cycle в средах со сборщиком мусора (GC) не возникают. Это ключевое отличие от систем с подсчетом ссылок (ARC, как в Swift/ObjC).

Как это работает:

  • В ARC: Объект освобождается, когда счетчик сильных ссылок на него достигает нуля. Цикл сильных ссылок мешает этому обнулению, вызывая утечку.
  • В GC (Java, .NET, Go и др.): Сборщик мусора периодически сканирует граф объектов, начиная с корневых ссылок (например, активные потоки, статические поля). Объекты, недостижимые из этих корней, помечаются на удаление, независимо от наличия ссылок друг на друга.

Пример цикла, который GC корректно соберет:

class Node {
    Node other;
}

Node a = new Node();
Node b = new Node();
a.other = b;
b.other = a; // Классический retain cycle

// Когда переменные a и b выйдут из области видимости (или будут перезаписаны),
// оба объекта Node станут недостижимыми из корней и будут собраны GC.

Однако retain cycle в GC-средах может вызывать другие проблемы:

  • Временное удержание памяти: Объекты в цикле будут жить до следующего прохода GC, что может увеличить пиковое потребление памяти.
  • Проблемы с финализаторами: Если объекты в цикле имеют финализаторы (finalize в Java), их порядок вызова может быть непредсказуемым.

Вывод: Retain cycle — это проблема архитектуры и читаемости кода в любом случае, но причина для паники из-за утечек памяти актуальна только для ARC.