Каковы корни?

Каковы корни в сборке мусора?

Я прочитал определение root как "любую ссылку, к которой у вас есть доступ к вашей программе", а определение live - это то, что используется объект, который может быть локальной переменной, статической переменной.

Меня немного смущает различие между корневыми и живыми объектами.

Что такое путь к корню? Как работают корневые и живые объекты?

Может кто-нибудь уточнить?

5 ответов

Решение

Если вы думаете об объектах в памяти как о дереве, "корнями" будут корневые узлы - каждый объект, немедленно доступный вашей программе.

Person p = new Person();
p.car = new Car(RED);
p.car.engine = new Engine();
p.car.horn = new AnnoyingHorn();

Есть четыре объекта; человек, красная машина, ее двигатель и гудок. Нарисуйте контрольный график:

     Person [p]
        |
     Car (red)
   /           \
Engine    AnnoyingHorn

И вы в конечном итоге Person в "корне" дерева. Он живой, потому что на него ссылается локальная переменная, p, который программа может использовать в любое время для ссылки на Person объект. Это также относится и к другим объектам, через p.car, p.car.engine, так далее.

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

Учтите, однако, если через некоторое время выполняется следующее:

p.car = new Car(BLUE);

И перерисовать график:

     Person [p]
        |
     Car (blue)       Car (red)
                    /           \
                Engine    AnnoyingHorn

Теперь Person доступен через p и синий автомобиль через p.car, но нет никакой возможности снова получить доступ к красной машине или ее частям - они не связаны с живым корнем. Их можно безопасно собрать.

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

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

Есть несколько видов корней GC. Один объект может принадлежать более чем одному виду корня. Коренные виды:

  • Класс - класс, загружаемый системным загрузчиком классов. Такие классы никогда не могут быть выгружены. Они могут содержать объекты через статические поля. Обратите внимание, что классы, загружаемые пользовательскими загрузчиками классов, не являются корнями, если только соответствующие экземпляры java.lang.Class не являются корнями других типов.
  • Тема - живая тема
  • Stack Local - локальная переменная или параметр метода Java
  • JNI Local - локальная переменная или параметр метода JNI
  • JNI Global - глобальная ссылка на JNI
  • Монитор используется - объекты, используемые в качестве монитора для синхронизации
  • Удерживаемые JVM - объекты, хранящиеся в сборщике мусора JVM для своих целей. На самом деле список таких объектов зависит от реализации JVM. Возможные известные случаи: загрузчик системных классов, несколько важных классов исключений, о которых знает JVM, несколько предварительно выделенных объектов для обработки исключений и пользовательские загрузчики классов, когда они находятся в процессе загрузки классов. К сожалению, JVM не предоставляет абсолютно никаких дополнительных деталей для таких объектов. Таким образом, аналитик должен решить, к какому случаю относится определенная "Удерживаемая JVM".

(кредит на сайте YourKit)

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

Корни или корни сборки мусора - это объекты, которые всегда доступны. Если объект всегда доступен, то он не подходит для сборки мусора; поэтому корни всегда не подходят для сбора. Это начальный набор объектов, из которого определяется достижимость всех других объектов в куче.

Другие объекты в куче, достижимые из корней сборки мусора, считаются живыми объектами и не могут быть собраны; недоступные объекты могут быть помечены для восстановления.

Я знаю Java больше, чем платформа.Net, поэтому я буду говорить только об одном. На платформе Java корни GC фактически зависят от реализации. Однако в большинстве сред выполнения корни GC являются операндами в стеке (поскольку они в настоящее время используются потоками) и классовыми (статическими) членами классов. Достижимость рассчитывается на основе этих объектов в большинстве JVM. В других случаях локальные параметры и операнды, используемые вызовами JNI, будут считаться частью корневого набора, а также использоваться для вычисления достижимости.

Я надеюсь, что это устранит все оставшиеся сомнения относительно того, что является корнем (набором) и что является живым объектом.

На веб-сайте IBM перечислено следующее как корни GC.

Обратите внимание, что некоторые из них являются искусственными конструкциями, выполняемыми анализатором памяти, но все же важно знать об этом, если вы просматриваете дамп кучи.

  • Системный класс

    Класс, который был загружен загрузчиком начальной загрузки или системным загрузчиком классов. Например, эта категория включает в себя все классы в файле rt.jar (часть среды выполнения Java), например, в пакете java.util.*.

  • JNI местный

    Локальная переменная в собственном коде, например, определяемый пользователем код JNI или внутренний код JVM.

  • JNI глобальный

    Глобальная переменная в собственном коде, например, определяемый пользователем код JNI или внутренний код JVM.

  • Блок резьбы

    Объект, на который ссылались из активного блока потока.

  • Нить

    Бегущая нить.

  • Занят монитор

    Все, что вызывало методы wait() или notify() или синхронизировалось, например, путем вызова метода synchronized(Object) или путем ввода метода synchronized. Если метод был статическим, корень является классом, в противном случае это объект.

  • Java местный

    Локальная переменная. Например, входные параметры или локально созданные объекты методов, которые все еще находятся в стеке потока. Родной стек

    Входные или выходные параметры в собственном коде, например, определяемый пользователем код JNI или внутренний код JVM. Многие методы имеют собственные части, а объекты, которые обрабатываются как параметры метода, становятся корнями сборки мусора. Например, параметры, используемые для файловых, сетевых, операций ввода-вывода или отражения.

  • Финалайзер

    Объект в очереди, ожидающий запуска финализатора.

  • незакрытых

    Объект, у которого есть метод finalize, но он не был завершен и еще не находится в очереди финализатора.

  • недостижимый

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

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

    По умолчанию недоступные объекты исключаются, когда анализатор памяти анализирует дамп кучи. Следовательно, эти объекты не отображаются в гистограмме, в дереве доминирования или в результатах запроса. Вы можете изменить это поведение, щелкнув Файл> Настройки... > IBM Diagnostic Tools for Java - Memory Analyzer, затем установив флажок Сохранить недоступные объекты.

  • Фрейм стека Java

    Фрейм стека Java, который содержит локальные переменные. Этот тип корня сборки мусора генерируется только в том случае, если вы задаете настройки для обработки фреймов стека Java как объектов. Для получения дополнительной информации см. Основы Java: потоки и запросы стека потоков.

  • неизвестный

    Объект неизвестного корневого типа. Некоторые дампы, такие как файлы IBM Portable Heap Dump (.phd), не имеют корневой информации. В этом случае анализатор Memory Analyzer помечает объекты, которые не имеют входящих ссылок или недоступны из любого другого корня, как неизвестные. Это действие гарантирует, что Memory Analyzer сохранит все объекты в дампе.

В Java я бы сказал, что потоки являются корневыми объектами. Каждый живой объект может быть возвращен в текущий поток. Например, на статический объект ссылается класс, на который ссылается загрузчик класса, на который ссылается другой класс, на который ссылается экземпляр этого класса,... на который ссылается Runnable, на который ссылается живой веткой. (Обратите внимание, что классы могут быть GC'ed, они не могут быть корнями)

Мы также можем рассмотреть "настоящий" корень для всех потоков, однако это выходит за рамки стандартной Java. Мы не можем сказать, что это такое и как оно ссылается на все темы.

Другие вопросы по тегам