Получает ли сборщик мусора весь .net Graph? - PullRequest
0 голосов
/ 20 октября 2018

Допустим, ObjectA имеет единственную ссылку на ObjectB, а ObjectB имеет единственную ссылку на ObjectC.Если у ObjectA больше нет ссылок на него, когда ObjectA будет собирать мусор, будут ли ObjectB и ObjectC также собирать мусор?

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

Например:

class Foo
{
    public string Name { get; set; } = "...";
    public object Ref { get; set; }

    ~Foo()
    {
        Console.WriteLine($"{Name} is finalized.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var objectA = new Foo
        {
            Name = "Object A",
            Ref = new Foo
            {
                Name = "Object B",
                Ref = new Foo
                {
                    Name = "Object C"
                }
            }
        };
        Console.WriteLine("Begin");
        objectA = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("End");
        Console.ReadKey();
    }
}

Выход:

Begin
Object C is finalized.
Object B is finalized.
Object A is finalized.
End

Другое дело, что это цикл ссылок.Если объект A ссылается на объект B, ссылка на объект C ссылается на объект A:

class Program
{
    static void Main(string[] args)
    {
        var objectA = new Foo
        {
            Name = "Object A",
            Ref = new Foo
            {
                Name = "Object B",
                Ref = new Foo
                {
                    Name = "Object C"
                }
            }
        };
        ((Foo)((Foo) objectA.Ref).Ref).Ref = objectA;
        Console.WriteLine("Begin");
        Console.WriteLine(objectA.Name);
        objectA = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("End");
    }
}

Ouput:

Begin
Object C is finalized.
Object B is finalized.
Object A is finalized.
End

Необходимо понимать, что начало графического объекта - это домен приложения.В последнем примере:

App Domain -> Object A -> Object B -> Object C -|
               ↑----------------------------|
0 голосов
/ 20 октября 2018

Это зависит от того, насколько точным вы хотите, чтобы ответ был.

Прежде всего, когда объект больше не имеет корневых ссылок, ссылающихся на него, объект считается «подходящим для сбора».

«Корневая ссылка» - это ссылка через любой путь, исходящий из «корня», который в конечном итоге ссылается на объект.Одним из таких типов корня являются все статические поля в домене приложения, другим могут быть локальные переменные в методах, все еще находящихся в стеке вызовов, при условии, что эти методы по-прежнему используются для этой ссылки.

Итак, давайте возьмем ваш пример.

Объект A относится к B, B относится к C. Другие ссылки не рассматриваются.

Ссылка от A до B удаляется, оставляя B без корневой ссылки.C также не имеет корневых ссылок, так как невозможно перейти из корня в C через другие объекты.

Таким образом, когда вы удаляете ссылку на B из A, B и Cтеперь имеет право на сбор .

Однако они не обязательно собираются немедленно и не должны собираться как часть одного и того же цикла сбора.

Очень упрощенноСистема управления памятью .NET построена на 3 разных кучах, от 0 до 2 поколения. Существует также «куча больших объектов», но это не обязательно для этого ответа.Поколение 0 - это место, где все объекты изначально создаются, и когда оно заполняется, выполняется цикл сборки мусора поколения 0, анализирующий, какие объекты все еще укоренены, а какие нет.

Все объекты, которые являютсяукоренившиеся выживают и становятся частью поколения 1 (следующего поколения), все объекты, у которых больше нет корневых ссылок, были собраны.Объекты с финализаторами не подчиняются этому правилу, но опять-таки это не очень актуально.

Когда поколение 1 заполняется, оно тоже собирается, перемещая выжившие объекты в поколение 2.

Поколения 0, 1 и 2 не обязательно собираются одновременно.Вы можете иметь несколько коллекций поколения 0, прежде чем станет необходимым коллекция поколения 1.

Таким образом, если B и C являются частью разных поколений, то нет, они не обязательно будут собираться одновременно.

Они сделали , однако, становятся имеющими право на сбор в то же время.

0 голосов
/ 20 октября 2018

Да.

Не думайте, что сборщик мусора ищет объекты, на которые нет ссылок.Думайте об этом как о поддержании объектов, которые делают имеют ссылки.

В основном: когда вы выделяете новый объект, откуда берется память?В любом месте в памяти, где нет объекта, который еще жив (то есть, он все еще может быть использован каким-либо образом при запуске кода).Любая часть памяти, которой больше не может достичь ни один выполняемый код, недоступна, и GC будет использовать недоступное пространство памяти для размещения новых объектов.

(Современные GC также перемещают объекты в памяти, чтобы упроститьвыделить новые, но это выходит за рамки этого ответа.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...