Skip to content

Latest commit

 

History

History
69 lines (49 loc) · 11.1 KB

File metadata and controls

69 lines (49 loc) · 11.1 KB

Оглавление

JVM

Сборка мусора. Как работает? Какие сборщики знаете? Какие есть области памяти в JVM? Что будет с двумя или более объектами, которые ссылаются только друг на друга, но больше не на кого и никому не нужны - как с ними поступит сборщик и как именно это будет делать?

Память в Java делится на Stack и Heap.

Stack - это область памяти, доступ к которой организован в порядке LIFO. Сюда помещается frame - локальные переменные и параметры вызываемого метода. Здесь можно сразу уточнить, что примитивы хранятся на стеке, а вот у объектов тут хранится только ссылка, а сами объекты в Heap. НО, благодаря Escape Analysis и скаляризации из Java 6, объекты, которые являются исключительно локальными и не возвращаются за пределы выполняемого метода, также сохраняются в стеке. Про Escape Analysis и скаляризацию есть доклад (видео или текст) Руслана Черемина, или ещё тут.

Frame создаётся и кладётся на Stack при вызове метода. Frame уничтожается, когда завершается его вызов метода, как в случае нормального завершения, так и в результате выброса неперехваченного исключения. У каждого потока есть свой Stack и он имеет ограниченный размер. Подробности можно посмотреть в JVM Specification.

Теперь про Heap и сборку мусора. Тут большинство просто хочет услышать то, что написано в одном из сообщений telegram-канала Senior's Blog. Процитирую основную часть здесь:

Heap делится на два поколения:
  1. Young Generation
    1. Eden
    2. Survivor 0 и Survivor 1
  2. Old Generation
    1. Tenured

Young разделен на три части: Eden, Survivor 0 и Survivor 1. В Eden создаются все новые объекты. Один из Survivor регионов всегда пустой. При полном заполнении региона Eden запускается малая сборка мусора, и все живые объекты из Eden и Survivor перемещаются в пустой Survivor, а Eden и использующийся Survivor полностью очищается. Это делается для уменьшения фрагментации памяти. Объекты, которые несколько раз перемещаются между Survivor, затем помещаются в Tenured.

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

Бывают еще объекты-акселераты, размер которых настолько велик, что создавать их в Eden, а потом таскать за собой по Survivor’ам слишком накладно. В этом случае они размещаются сразу в Tenured.

Младшее поколение занимает одну треть всей кучи, а старшее, соответственно, две трети. При этом каждый регион Survivor занимает одну десятую младшего поколения, то есть Eden занимает восемь десятых.

Существуют следующие реализации GC:

Если совсем кратко, то можно ознакомиться тут и вот тут.

Почитать на Хабре подробнее про сборку мусора в Java можно в серии статей "Дюк, вынеси мусор!" от @alygin - раз, два, три.

Послушать про работу с памятью и сборщиках мусора можно в выпуске 74 подкаста Podlodka с Алексеем Шипилёвом в гостях. Обязательно загляните в полезные ссылки к выпуску.

Ещё можно вспомнить про:

  • Method Area - область памяти с информацией о классах, включая статические поля. Одна на всю JVM.
  • Program Counter (PC) Register - отдельный на каждый поток регистр для хранения адреса текущей выполняемой инструкции.
  • Run-time Constant Pool - выделяется из Method Area для каждого класса или интерфейса. Грубо говоря, хранит литералы. Подробнее.
  • Native Method Stack - собственно Stack для работы нативных методов.

Дополнительно про gc и саму JVM (ох, бохатая и животрепещущая тема):

  • На богомерзком medium в картинках
  • Перевод статьи Алексея Шипилёва на Хабре - Самодельный сборщик мусора для OpenJDK
  • Отрывок из Java Garbage Collection Handbook про reachability algorithm
  • Статейка на Википедии про Tracing garbage collection
  • Доклад Simone Bordet про ZGC и Shenandoah
  • JVM Anatomy Quarks - серия постов от Алексея Шипилёва про устройство JVM. Это просто клад, за который будут воевать пришельцы на постапокалиптическую Землю, чтобы разгадать, как работает эта чёртва шайтан-виртуал-машина и промышленный код почивших человеков.

к содержанию