В Java управление памятью и сборка мусора осуществляются автоматически JVM. В случае циклических ссылок, где два или более объектов ссылаются друг на друга, стандартный механизм подсчета ссылок (reference counting) неэффективен, поскольку циклические ссылки не позволят уменьшить счетчик ссылок до нуля. Однако, Java использует более сложные алгоритмы сборки мусора, такие как маркировка-сжатие (mark-and-sweep) и алгоритмы поколения, которые способны обнаруживать и собирать циклически связанные, но неиспользуемые объекты.
🚩Как работает алгоритм маркировка-сжатие
🟠Маркировка (Mark Phase)
Сначала алгоритм начинается с корневых объектов (root objects), таких как статические переменные, локальные переменные в стеке текущего потока, и помечает все доступные объекты, начиная с этих корней.
🟠Сжатие (Sweep Phase)
Все объекты, которые не были помечены в фазе маркировки, считаются недоступными и могут быть собраны мусорщиком.
🚩Пример циклических ссылок
public class A {
B b;
}
public class B {
A a;
}
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
// Теперь a и b ссылаются друг на друга
a = null;
b = null;
// Оба объекта теперь недоступны
// Сборщик мусора сможет их собрать
}
}🚩Как сборщик мусора обрабатывает циклические ссылки
🟠Маркировка (Mark Phase)
Когда сборщик мусора выполняет фазу маркировки, он начнет с корневых объектов и будет следовать по всем доступным ссылкам. В этом примере, после того как
a и b установлены в null, объекты класса A и B больше не будут доступны из корневых объектов.🟠Сжатие (Sweep Phase)
Объекты
A и B не помечены как доступные, поэтому они будут собраны сборщиком мусора.🚩Демонстрация работы сборщика мусора
Чтобы демонстрировать работу сборщика мусора и показать, что объекты с циклическими ссылками могут быть собраны, можно использовать отладочные инструменты или включить журналирование сборки мусора с помощью аргументов JVM.
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps Main
Ставь 👍 и забирай 📚 Базу знаний