Car myCar = new Car;
myCar = null;
}
Когда ссылке на объект присваивается null
myCar в данном примере) больше не указывает на какой-либо объект. Если теперь снова с помощью утилиты ildasm.exe просмотреть код CIL модифицированного метода MakeACar, то можно обнаружить в нем код операции ldnull (заталкивает значение null в виртуальный стек выполнения), за которым следует код операции stloc.0 (устанавливает для переменной ссылку null):.method assembly hidebysig static
void '<
{
// Code size 10 (0xa)
.maxstack 1
.locals init (class SimpleGC.Car V_0)
IL_0000: nop
IL_0001: newobj instance void SimpleGC.Car::.ctor
IL_0006: stloc.0
IL_0007: ldnull
IL_0008: stloc.0
IL_0009: ret
} // end of method '
Тем не менее, вы должны понимать, что присваивание ссылке значения null
Выяснение, нужен ли объект
Теперь вернемся к вопросу о том, как сборщик мусора определяет момент, когда объект больше не нужен. Для выяснения, активен ли объект, сборщик мусора использует следующую информацию.
• Корневые элементы в стеке: переменные в стеке, предоставляемые компилятором и средством прохода по стеку.
• Дескрипторы сборки мусора: дескрипторы, указывающие на объекты, на которые можно ссылаться из кода или исполняющей среды.
• Статические данные: статические объекты в доменах приложений, которые могут ссылаться на другие объекты.
Во время процесса сборки мусора исполняющая среда будет исследовать объекты в управляемой куче с целью выяснения, являются ли они по-прежнему достижимыми (т.е. корневыми) для приложения. Для такой цели исполняющая среда будет строить
Предположим, что в управляемой куче находится набор объектов с именами А, В, С, D, E, F и G. Во время сборки мусора эти объекты (а также любые внутренние объектные ссылки, которые они могут содержать) будут проверяться. После построения графа недостижимые объекты (пусть ими будут объекты С и F) помечаются как являющиеся мусором. На рис. 9.3 показан возможный граф объектов для только что описанного сценария (линии со стрелками можно читать как "зависит от" или "требует", т.е. Е зависит от G и В, А не зависит ни от чего и т.д.).
После того как объекты помечены для уничтожения (в данном случае С и F, т.к. они не учтены в графе объектов), они удаляются из памяти. Оставшееся пространство в куче сжимается, что в свою очередь вынуждает исполняющую среду изменить лежащие в основе указатели для ссылки на корректные местоположения в памяти (это делается автоматически и прозрачно). И последнее, но не менее важное действие — указатель на следующий объект перенастраивается так, чтобы указывать на следующую доступную область памяти. Конечный результат описанных изменений представлен на рис. 9.4.
На заметку!
Строго говоря, сборщик мусора использует две отдельные кучи, одна из которых предназначена специально для хранения крупных объектов. Во время сборки мусора обращение к данной куче производится менее часто из-за возможного снижения производительности, связанного с перемещением больших объектов. В .NET Core куча для хранения крупных объектов может быть уплотнена по запросу или при достижении необязательных жестких границ, устанавливающих абсолютную или процентную степень использования памяти.Понятие поколений объектов
Когда исполняющая среда пытается найти недостижимые объекты, она не проверяет буквально каждый объект, помещенный в управляемую кучу. Очевидно, это потребовало бы значительного времени, тем более в крупных (т.е. реальных) приложениях.
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT