Сбор мусора - корневые узлы

Недавно я прочитал фрагменты о сборке мусора (в основном на Java), и один вопрос по-прежнему остается без ответа: как JVM (или система времени выполнения в целом) отслеживает текущие объекты в реальном времени?

Я понимаю, что объекты находятся в стеке, поэтому все локальные переменные или функциональные параметры, которые ARE объекты. Рольблема с этим соглашением заключается в том, что всякий раз, когда система времени выполнения проверяет, что в данный момент находится в стеке, как бы она различала ссылочную переменную и простой int? он не может, может ли это?

Следовательно, должен существовать какой-то механизм, позволяющий runtime строить исходный список живых объектов для прохождения фазы отметки...

Ответ 1

Я нашел ответ, предоставленный greyfairer, неправильным. Время выполнения JVM не собирает корневой набор из стека, если посмотреть, какие байт-коды используются для ввода данных в стек. Рамка стека состоит из 4-байтовых (32-битных арки) слотов. Каждый слот может быть ссылкой на объект кучи или примитивное значение, такое как int. Когда требуется GC, среда выполнения сканирует стек, сверху вниз. Для каждого слота он содержит ссылку, если:

а. Он выровнен на границе 4 байта.

б. Значение в слоте указывает на область кучи (между нижней и верхней границей).

с. Набор allocbit установлен. Allocbit - это флаг, указывающий, выделено ли соответствующее ему место памяти.

Вот моя ссылка: http://www.ibm.com/developerworks/ibm/library/i-garbage2/.

Существуют и другие методы поиска корневого набора (не в Java). Например, поскольку указатели обычно выравниваются с границей 4/8 байтов, первый бит может использоваться для указания, является ли слот примитивным значением или указателем: для примитивных значений первый бит устанавливается равным 1. Недостатком этого является что у вас есть только 31 бит (32 бита), чтобы представлять целое число, и все операции над примитивными значениями включают в себя смещение, что очевидно накладные расходы.

Кроме того, вы можете создавать все типы, включая int, выделенные в куче. То есть все вещи являются объектами. Затем все слоты в кадре стека являются ссылками.

Ответ 2

Время выполнения может отлично различать опорные переменные и примитивы, поскольку это в скомпилированном байт-коде.

Например, если функция f1 вызывает функцию f2 (int i, Object o, long l), вызывающая функция f1 будет выталкивать 4 байта в стек (или в регистр), представляющий i, 4 (или 8?), байты для ссылки на o и 8 байтов для l. Вызываемая функция f2 знает, где найти эти байты в стеке, и может потенциально копировать ссылку на какой-либо объект в куче или нет. Когда функция f2 вернется, вызывающая функция сбросит параметры из стека.

Время выполнения интерпретирует байт-код и записывает то, что он толкает или падает на стек, поэтому он знает, что является ссылкой и что является примитивным значением.

Согласно http://www.javacoffeebreak.com/articles/thinkinginjava/abitaboutgarbagecollection.html, java использует трассировочный сборщик мусора, а не алгоритм подсчета ссылок.

Ответ 3

VM HotSpot генерирует карту GC для каждой скомпилированной подпрограммы, которая содержит информацию о том, где корни. Например, предположим, что он скомпилировал подпрограмму для машинного кода (принцип тот же для байтового кода), длина которого составляет 120 байтов, тогда карта GC для него может выглядеть примерно так:

0 : [RAX, RBX]
4 : [RAX, [RSP+0]]
10 : [RBX, RSI, [RSP+0]]
...
120 : [[RSP+0],[RSP+8]]

Здесь [RSP+x] должен указывать местоположения стека и регистры R??. Поэтому, если поток остановлен в команде сборки со смещением 10 и выполняется цикл gc, то HotSpot знает, что три корня находятся в RBX, RSI и [RSP+0]. Он отслеживает эти корни и обновляет указатели, если он должен перемещать объекты.

Формат, который я описал для карты GC, предназначен только для демонстрации принципа и, очевидно, не того, что использует HotSpot. Он не является полным, потому что он не содержит информации о регистрах и слотах стека, которые содержат примитивные значения в реальном времени, и не просто использовать пространство для списка для каждого смещения команды. Есть много способов, которыми вы можете упаковывать информацию гораздо более эффективным способом.