Принципы работы сборщика мусора java

Избавляемся от мусора в Java

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

Кто занимается этой очисткой? Как и когда очищается память? Как выглядит структура памяти? Давайте разберем с этим подробнее.

Структура памяти Java

Память в Java состоит из следующих областей:

Структура памяти Java

Native Memory — вся доступная системная память.

Heap (куча) — часть native memory, выделенная для кучи. Здесь JVM хранит объекты. Это общее пространство для всех потоков приложения. Размер этой области памяти настраивается с помощью параметра -Xms (минимальный размер) и -Xmx (максимальный размер).

Stack (стек) — используется для хранения локальных переменных и стека вызовов метода. Для каждого потока выделяется свой стек.

Metaspace (метаданные) — в этой памяти хранятся метаданные классов и статические переменные. Это пространство также является общими для всех. Так как metaspace является частью native memory, то его размер зависит от платформы. Верхний предел объема памяти, используемой для metaspace, можно настроить с помощью флага MaxMetaspaceSize.

PermGen (Permanent Generation, постоянное поколение) присутствовало до Java 7. Начиная с Java 8 ему на смену пришла область Metaspace.

CodeCache (кэш кода) — JIT-компилятор компилирует часто исполняемый код, преобразует его в нативный машинный код и кеширует для более быстрого выполнения. Это тоже часть native memory.

Сборка мусора: введение

Что такое «мусор»? Мусором считается объект, который больше не может быть достигнут по ссылке из какого-либо объекта. Поскольку такие объекты больше не используются в приложении, то их можно удалить из памяти.

Например, на диаграмме ниже объект fruit2 может быть удален из памяти, поскольку на него нет ссылок.

Мусор

Что такое сборка мусора? Сборка мусора — это процесс автоматического управления памятью. Освобождение памяти (путем очистки мусора) выполняется автоматически специальным компонентом JVM — сборщиком мусора (Garbage Collector, GC). Нам, как программистам, нет необходимости вмешиваться в процесс сборки мусора.

Читайте также:  Css высота блока зависит от ширины

Источник: Oracle.com

Сборка мусора: процесс

Для сборки мусора используется алгоритм пометок (Mark & Sweep). Этот алгоритм состоит из трех этапов:

Mark & Sweep GC

  1. Mark (маркировка). На первом этапе GC сканирует все объекты и помечает живые (объекты, которые все еще используются). На этом шаге выполнение программы приостанавливается. Поэтому этот шаг также называется «Stop the World» .
  2. Sweep (очистка). На этом шаге освобождается память, занятая объектами, не отмеченными на предыдущем шаге.
  3. Compact (уплотнение). Объекты, пережившие очистку, перемещаются в единый непрерывный блок памяти. Это уменьшает фрагментацию кучи и позволяет проще и быстрее размещать новые объекты.

Поколения объектов

Что такое поколения объектов?

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

Поколения в куче

  1. Young Generation (молодое поколение). Здесь создаются новые объекты. Область young generation разделена на три части раздела: Eden (Эдем), S0 и S1 (Survivor Space — область для выживших).
  2. Old Generation (старое поколение). Здесь хранятся давно живущие объекты.

Что такое Stop the World?

Когда запускается этап mark, работа приложения останавливается. После завершения mark приложение возобновляет свою работу. Любая сборка мусора — это «Stop the World».

Что такое гипотеза о поколениях?

Как уже упоминалось ранее, для оптимизации этапов mark и sweep используются поколения. Гипотеза о поколениях говорит о следующем:

  1. Большинство объектов живут недолго.
  2. Если объект выживает, то он, скорее всего, будет жить вечно.
  3. Этапы mark и sweep занимают меньше времени при большом количестве мусора. То есть маркировка будет происходить быстрее, если анализируемая область небольшая и в ней много мертвых объектов.

Таким образом, алгоритм сборки мусора, использующий поколения, выглядит следующим образом:

Сборка мусора поколениями

  1. Новые объекты создаются в области Eden. Области Survivor (S0, S1) на данный момент пустые.
  2. Когда область Eden заполняется, происходит минорная сборка мусора (Minor GC). Minor GC — это процесс, при котором операции mark и sweep выполняются для young generation (молодого поколения).
  3. После Minor GC живые объекты перемещаются в одну из областей Survivor (например, S0). Мертвые объекты полностью удаляются.
  4. По мере работы приложения пространство Eden заполняется новыми объектами. При очередном Minor GC области young generation и S0 очищаются. На этот раз выжившие объекты перемещаются в область S1, и их возраст увеличивается (отметка о том, что они пережили сборку мусора).
  5. При следующем Minor GC процесс повторяется. Однако на этот раз области Survivor меняются местами. Живые объекты перемещаются в S0 и у них увеличивается возраст. Области Eden и S1 очищаются.
  6. Объекты между областями Survivor копируются определенное количество раз (пока не переживут определенное количество Minor GC) или пока там достаточно места. Затем эти объекты копируются в область Old.
  7. Major GC. При Major GC этапы mark и sweep выполняются для Old Generation. Major GC работает медленнее по сравнению с Minor GC, поскольку старое поколение в основном состоит из живых объектов.
Читайте также:  Html page right to left

Преимущества использования поколений

Minor GC происходит в меньшей части кучи (~ 2/3 от кучи). Этап маркировки эффективен, потому что область небольшая и состоит в основном из мертвых объектов.

Недостатки использования поколений

В каждый момент времени одно из пространств Survivor (S0 или S1) пустое и не используется.

Сборка мусора: флаги

В этом разделе приведены некоторые важные флаги, которые можно использовать для настройки процесса сборки мусора.

Источник

Сборщик мусора в Java (Garbage Collector)

Java-университет

Линия поведения сборщика мусора (утилизатора памяти)

Сборка мусора - 1

Java-программисту не нужно следить за распределением памяти, так как сборщик мусора управляет памятью автоматически. Сборщик мусора (Garbage Collector) запускается виртуальной машиной Java (JVM). Сборщик мусора — это низкоприоритетный процесс, который запускается периодически и освобождает память, использованную объектами, которые больше не нужны. Разные JVM имеют отличные друг от друга алгоритмы сбора мусора. Существует несколько используемых алгоритмов, например: алгоритм подсчёта ссылок или алгоритмы разметки и очистки.

Запуск сборщика мусора в Java

JVM обычно запускает сборщик мусора при низком уровне свободной памяти. Но работа сборщика мусора не гарантирует, что всегда будет оставаться достаточно свободной памяти. Если памяти недостаточно даже после восстановления, JVM генерирует исключение OutOfMemoryError. Обратите внимание, что перед генерированием исключения JVM обязательно запускает сборщик мусора как минимум 1 раз. Вы можете запросить запуск сборщика мусора в Java, но вы не можете принудительно задавать это действие.

Запрос запуска сборщика мусора

 System.gc() Runtime.getRuntime().gc() 

Пригодность для запуска сборщика мусора

  • Если переменная ссылочного типа, которая ссылается на объект, установлена в положение «0», объект подлежит утилизации, в том случае, если на него нет других ссылок.
  • Если переменная ссылочного типа, которая ссылается на объект, создана для ссылки на другой объект, объект подлежит утилизации, в том случае, если на него нет других ссылок.
  • Объекты, созданные локально в методе, подлежат утилизации, когда метод завершает работу, если только они не экспортируются из этого метода (т.е, возвращаются или генерируются как исключение).
  • Объекты, которые ссылаются друг на друга, могут подлежать утилизации, если ни один из них не доступен живому потоку.
Читайте также:  Python requests post files

В этом примере объект Integer (целочисленный), на который первоначально ссылается указатель o1 может подвергаться утилизации после строки 3, так как o1 теперь ссылается на объект String (строковый). Несмотря на то, что o2 создан для ссылки к нулю, объект String (строковый) не подлежит утилизации, так как o1 ссылается на него.

Финализация

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

 protected void finalize() throws Throwable 

Если незарегистрированное исключение генерируется методом finalize() , то исключение игнорируется и финализация этого объекта прекращается. Метод finalize() будет активизирован только один раз за время существования объекта. Возможно использование метода finalize() любого объекта, чтобы защитить его от утилизации. Но в этом случае сборщик мусора уже не активирует finalize() для этого объекта. Метод finalize() всегда будет активизирован один раз перед тем, как объект будет удалён сборщиком мусора. Однако, возможно, что метод finalize() не будет активизирован для данного объекта за всё время его существования, так как он может не подлежать утилизации.

Резюме

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

Упражнение

Варианты ответа: A. 0 B. 1 C. 2 D. 3 E. Код не возможно скомпилировать Правильный вариант: B Пояснение: из трёх объектов, созданных в строках 1, 2 и 3, только объект Integer подлежит утилизации в конце строки 7. Переменная ссылки, a, которая первоначально ссылалась на объект Integer , ссылается на объект String в строке 5. Таким образом, Integer oбъект подлежит утилизации после строки 5, так как нет переменных, которые ссылаются на него. Переменные b и c ссылаются на объекты String и Long объекты в строках 6 и 7, поэтому они не подлежат утилизации.

Источник

Оцените статью