Что такое корневая ссылка? - PullRequest
3 голосов
/ 01 мая 2010
class GCTest {
     static Object r1; 

     static void Main() {
         r1 = new Object();
         Object r2 = new Object();
         Object r3 = new Object();
         System.GC.Collect(); // what can be reclaimed here ?

         r1 = null;
         r3.ToString();
         System.GC.Collect(); // what can be reclaimed here ?
     }
    }

// код из - Essential .Net * DonBox

Ответы [ 6 ]

3 голосов
/ 01 мая 2010

В первой строке больше нет ссылок на r2, поэтому этот объект может быть восстановлен в этой точке. В последней строке объект, созданный для r1, больше не имеет ссылки, а локальные переменные r2 и r3 заканчиваются, поэтому все три объекта могут быть восстановлены в этой точке. Однако это будет зависеть от того, как все это скомпилировано.

Все три являются корневыми ссылками, поскольку ничто иное не относится к ним. Если бы r1 было полем экземпляра, а не статическим, то ссылка на ваш класс GCTest сделала бы r1 ссылку , а не корневой ссылкой.

2 голосов
/ 03 мая 2010

ГХ может собрать любой объект, для которого он может доказать , что он не имеет значения для приложения. Можно подумать об этом следующим образом: объекты выделяются навсегда , но реализации разрешено восстанавливать память, если она гарантирует, что вы ее не заметите.

В вашем примере, в первом GC.Collect() первая ссылка на объект была записана в r1, а r1 - статическая переменная, таким образом, как-то «постоянная». С точки зрения GC, практически любой код может использовать эту статическую переменную, поэтому GC не может гарантировать, что первый объект не будет использоваться. Поэтому он не может собрать это. Второй объект, с другой стороны, записывается в переменную local . Локальная переменная ограничена кодом метода (он исчезает при выходе из метода), и GC может заметить, что r2 больше не будет использоваться (GC нужно только смотреть на метод, а не весь код, поэтому это часть того, что GC может разумно сделать). Поэтому GC может собрать второй объект (здесь нет никаких обязательств).

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

Конечно, GC также может не собирать вещи. Весь смысл GC заключается в том, что он работает "за сценой", не влияя на выполнение кода (это не совсем верно при наличии финализации, но это дополнительный уровень сложности, который не следует предполагать, пока вы не освоите основы) .

Статья Уилсона действительно необходима для чтения всем, кто хочет понять, что делает сборка мусора.

2 голосов
/ 01 мая 2010

Попробуйте свой код с WeakReference, и вы увидите, когда эти ссылки живы. Попробуйте также выйти за пределы вашего метода. GC только восстанавливает r1. WeakReference поможет вам лучше понять, когда ваши ссылки исчезнут.

Ответ за исключением, конечно, бессмыслица. Единственное исключение, которое может r3.ToString() подняться - исключение нулевой ссылки, но если r3 равно нулю.

0 голосов
/ 01 мая 2010

Хотя я не могу дать подробный ответ на ваш вопрос, я могу указать вам хорошую статью о методах сбора мусора:

Пол Р. Уилсон (1994): Однопроцессорные методы сбора мусора

Если я правильно помню, оно содержит определение корневых ссылок.

0 голосов
/ 01 мая 2010
  • объект, который выделен в Main () и назначен для r1, будет объединен, потому что он недоступен после того, как r1 установлен в нуль.
  • r2 и r3 являются локальными переменными в Main (), и поэтому они являются корнями в этом контексте.
0 голосов
/ 01 мая 2010

Для меня это означает первый объект в цепочке ссылок. то есть A относится к B и B к C и т. д. A является Корнем, поскольку ничто иное не относится к нему.

На первом.

r1 Статичен, и тест ГХ содержит ссылку на него, поэтому его нельзя собрать, а r2 можно собрать. r3 будет, если вы не в отладчике или GC. KeepAlive называется

На втором

r1 можно собирать, так как он больше не входит в область видимости. г2 уже собран И в зависимости от того, был ли собран r3, он мог вызвать исключение или будет собран.

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