Ответ
Нет, классические утечки памяти из-за 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.