Сборка мусора - корневые узлы - PullRequest
11 голосов
/ 13 декабря 2011

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

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

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

Ответы [ 3 ]

6 голосов
/ 23 августа 2012

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

a.Выравнивается на границе 4 байта.

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

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

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

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

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

2 голосов
/ 13 декабря 2011

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

Например, если функция 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 использует трассировщик сборщика мусора , а не алгоритм подсчета ссылок.

1 голос
/ 11 сентября 2016

HotSpot VM генерирует карту 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. Он не является полным, поскольку он не содержит информации о регистрах и слотах стека, которые содержат примитивные действующие значения, и неэффективно использовать список для каждого смещения инструкции. Есть много способов, которыми вы можете упаковать информацию гораздо более эффективным способом.

...