Автор оригинала: Ali Dehghani.
1. Обзор
В этой быстрой статье мы увидим, как JVM гарантирует сбор недостижимых, но циклических ссылок.
Во-первых, мы будем изучать различные типы алгоритмов GC. После этого мы увидим, как циклические ссылки обрабатываются в JVM.
Стоит также отметить, что GC не является частью спецификации JVM и остается на усмотрение . Таким образом, каждая реализация JVM может иметь различные стратегии GC или вообще не иметь их.
В этой статье мы сосредоточиваемся на одной конкретной реализации СПМ: СПМ HotSpot. Мы также можем использовать термины JVM и HotSpot JVM взаимозаменяемы на протяжении всей статьи.
2. Подсчет ссылок
Алгоритмы подсчета ссылок GC связывают количество ссылок с каждым объектом. Эти алгоритмы считают объект живым до тех пор, пока количество ссылок на этот объект превышает нулевой . Как правило, время выполнения хранит количество ссылок в заголовке объекта.
В очень наивной реализации каждая новая ссылка на объект должна вызывать увеличение счета атомных ссылок. Аналогичным образом, каждый новый dereference должен вызвать атомное decrement.
Swift программирования язык использует форму подсчета ссылок для управления памятью. Кроме того, в JVM нет алгоритма GC, основанного на подсчете ссылок.
2.1. Плюсы и минусы
С другой стороны, подсчет ссылок может распределять расходы на управление памятью на протяжении всего жизненного цикла приложения, так как периодических икот GC нет. Кроме того, он потенциально может уничтожить объекты, как только их количество ссылок достигнет нуля и станет мусором.
Подсчет ссылок не бесплатный обед, либо. В наивной реализации обновление эталонного счета может быть неэффективным, поскольку нам необходимо приращение или декрементирование его атоманно. Немногие оптимизации могут сделать подсчет ссылок более эффективным в этом отношении, например, отложенные или буферные подходы к подсчету ссылок.
Тем не менее, есть еще одна серьезная проблема с подсчетом ссылок: он не может вернуть циклические ссылки .
Например, предположим, что объект относится к объекту B и наоборот. Даже если и B становятся недоступными от остальной части диаграммы объектов, их количество ссылок никогда не достигнет нуля. Это потому, что они по-прежнему держать ссылку друг на друга.
Как оказалось, такого рода циклические ссылки довольно распространены в информатике. Например, рассмотрим следующий список, связанный вдвойне. Во-первых, другой объект имеет ссылку на список:
Связанный список можно выйти из объекта D, поэтому он не должен быть собран, и подсчеты ссылок приведены в соответствие с этим ожиданием. Теперь предположим, что объект D сама становится недостижимой:
Несмотря на то, что связанный список сейчас также недоступен, количество ссылок на его компоненты составляет более одного. Поэтому с этой наивной реализацией подсчета ссылок время выполнения не будет рассматривать этот связанный список как мусор, даже если он .
3. Отслеживание ГК
Отслеживание коллекторов будет определять доступность объектов, отслеживая их из набора корневых объектов, известных как корни GC . Если объект достижим из корневого объекта, прямо или косвенно, то он будет считаться живым. Другие недоступны и кандидаты на сбор:
Вот как работает простой коллектор трассировки. Начиная с корней GC, он повторяет график объектов повторно до тех пор, пока не будет больше серых объектов, оставшихся для посещения. В конце концов, он считает все белые объекты недоступными и кандидатами на сбор. Это простое изображение трехцветного алгоритма маркировки.
Мы можем думать о корнях GC как об объектах, которые, как мы уверены, живы . Например, это некоторые корни GC в Java и JVM:
- Локальные переменные или что-либо кадры стека имеют в виду прямо сейчас. Эти переменные используются методами выполнения в настоящее время, поэтому мы не хотим их собирать
- Потоки в реальном 200
- Статические переменные
- Классы, загруженные системный классоугрузчик
- JNI местных жителей и глобальных
Отслеживание коллекторов, в отличие от сборщиков ссылок, будет выполнять процесс сбора периодически. Таким образом, большую часть времени, распределения и назначения должны работать быстро. Однако, когда GC стартует, там могут быть некоторые икоты.
С другой стороны, эти алгоритмы GC не будут страдать от циклических ссылок . Вместо того, чтобы считать ссылки на каждый объект, они пересекают график объектов, начиная с корней GC. Поэтому, даже если есть некоторые циклические ссылки, объекты будут собираться до тех пор, пока они недоступны, как показано на приведенной выше диаграмме.
Довольно интересно, что использование коллектора отслеживания резервного копирования в тандеме с подсчетом ссылок GC является одним из обычных подходов к исправлению циклических ссылок при подсчете ссылок.
3.1. СПМ HotSpot
Все Реализации GC в HotSpot JVM, на данный день, являются отслеживания коллекционеров, в том числе CMS, G1, и ЗГК . Таким образом, JVM не будет страдать от циклической справочной проблемы. Это ключ вынос из этой статьи!
4. Заключение
В этой быстрой статье мы увидели, как JVM обрабатывает циклические ссылки.
Для более детальной обработки сбора мусора настоятельно рекомендуется проверить справочник по сбору .