Какой сборщик мусора разбивает память на множество регионов одинакового размера

Обновлено: 07.07.2024

Вновь созданные объекты начинаются в Young Generation. Его еще называют ясли, так как здесь начинают жить новые объекты. Young Generation подразделяется на Eden Space, где начинаются все новые объекты, и два пространства Survivor , где объекты перемещаются из Eden после сохранения (surviving) в одном цикле сборки мусора. Они вызывают повторную сборку мусора, когда объекты собираются сборщиком мусора из Young Generation. Eden Space Все новые объекты сначала создаются в Eden Space. Незначительный сбор мусора сработает, когда он достигнет порога, определяемого JVM. Упомянутые объекты перемещаются из Eden Space в пространство первого сохранения (‘Eden’ and ‘from’ —> ‘to’). Объекты, на которые нет ссылок, удаляются при очистке Eden Space. Survivor 0 (S0) and Survivor 1 (S1) Оба поля survivor (From and to) начинаются пустыми. Когда происходит повторная сборка мусора, все объекты, на которые есть ссылки, перемещаются в оставшееся пространство. Когда сборка мусора закончится, места (имена) survivor «from» и «to» меняются местами. Если во время предыдущей сборки мусора S1 был в роли «to», то теперь S1 заполнен и становится «from». Соответственно, если S0 пусто, то оно станет «to».

Old Generation

Permanent Generation

Типы сборки мусора

Сборки мусора, очищающие различные части внутри кучи, часто называют Minor, Major и Full сборками мусора. Но, поскольку термины Minor, Major и Full широко используются и без надлежащего определения, мы рассмотрим объяснение всех этих типов сборки мусора.

Minor Garbage Collection

Сборка мусора из пространства Young Generation называется Minor Garbage Collection. Этот тип сборки всегда запускается, когда JVM не может выделить место для нового объекта, то есть когда Eden Space заполняется. Таким образом, чем выше скорость выделения, тем чаще происходит Minor Garbage Collection.

Major Garbage Collection

Major Garbage Collection очищает Tenured (старое пространство). Поскольку Old Generation больше по размеру, сборка происходит реже, чем у Young Generation. Когда объекты исчезают из Old Generation, мы говорим, что произошел «большая сборка мусора». Сборщик Old Generation попытается предугадать, когда ему нужно начать сборку, чтобы избежать неудач в продвижении со стороны Young Generation. Сборщики отслеживают порог заполнения для Old Generation и начинают сборку, когда этот порог превышен. Если этого порога недостаточно для удовлетворения требований продвижения, запускается «Full Garbage Collection».

Full Garbage Collection

Full Garbage Collection очищает всю кучу — как молодые, так и старые пространства. Многие путаются между Major (только OLD поколение) и Full GC (Young + OLD (Heap)). Full Garbage Collection включает продвижение всех живых объектов от молодого до старого поколения после сборки и уплотнения старого поколения. Полная сборка мусора будет остановкой для Stop-the-World. Она следит за тем, чтобы новые объекты не выделялись и объекты не становились недоступными во время работы сборщика.

15 важных вопросов про Spring на техническом собеседовании

1. Что такое Spring?

Ответ: Spring — это фреймворк с открытым исходным кодом для разработки приложений на Java. Основные функции Spring Framework можно использовать при разработке любого приложения Java, также имеются расширения для создания веб-приложений на основе платформы Java EE. Фреймворк Spring нацелен на упрощение использования J2EE в разработке, и улучшение практики программирования путем включения модели на основе POJO (Plain Old Java Object).

2. Какова область действия по умолчанию у bean-компонента в Spring framework?

Ответ: Область действия bean-компонента по умолчанию — Singleton (шаблон проектирования).

3. Что такое Bean wiring?

Ответ: Bean wiring (подключение Bean) — это действие по созданию ассоциаций между компонентами приложения (beans) в контейнере Spring.

4. Что такое Spring Security?

Ответ: Spring Security — это отдельный модуль инфраструктуры Spring, который фокусируется на предоставлении методов аутентификации и авторизации в приложениях Java. Он также устраняет большинство распространенных уязвимостей безопасности, таких как атаки CSRF. Чтобы использовать Spring Security в веб-приложениях, можно начать с простой аннотации: @EnableWebSecurity.

5. Что содержится в определении bean-компонента?

  • Как создать bean;
  • Подробности жизненного цикла bean;
  • Зависимости bean.

6. Что такое Spring Boot?

Ответ: Spring Boot — это проект, который предоставляет предварительно настроенный набор фреймворков для уменьшения шаблонной конфигурации, чтобы вы могли запускать и запускать приложение Spring с минимальным объемом кода.

7. Что такое DispatcherServlet и для чего он используется?

Ответ: DispatcherServlet — это реализация шаблона проектирования Front Controller, который обрабатывает все входящие веб-запросы к приложению Spring MVC. Шаблон Front Controller (шаблон проектирования корпоративного приложения) — это распространенный шаблон в веб-приложениях, задача которого заключается в получении всего запроса и его маршрутизации в различные компоненты приложения для фактической обработки. В Spring MVC DispatcherServlet используется для поиска правильного контроллера для обработки запроса. Это делается с помощью сопоставления обработчиков: например, аннотации @RequestMapping.

8. Нужен ли spring-mvc.jar в пути к классам или он является частью spring-core?

Ответ: Spring-mvc.jar является частью spring-core, что означает, что если вы хотите использовать инфраструктуру Spring MVC в своем проекте Java, то вы должны включить ее spring-mvc.jar в путь к классам вашего приложения. В веб-приложении Java spring-mvc.jar обычно помещается в папку /WEB-INF/lib.

9. Каковы преимущества использования Spring?

  • Легкость — Spring относительно легкий, когда дело касается размера и прозрачности. Базовая версия Spring Framework составляет около 2 МБ.
  • Инверсия управления (Inversion of control, IOC) — Слабая связанность (loose coupling) достигается в Spring с использованием техники инверсии управления. Объекты предоставляют свои зависимости вместо того, чтобы создавать или искать зависимые объекты.
  • Аспектно-ориентированность — Spring поддерживает аспектно-ориентированное программирование и обеспечивает согласованную разработку, отделяя бизнес-логику приложения от системных служб.
  • Контейнеры — Spring Container создаёт объекты, связывает их вместе, настраивает и управляет ими от создания до момента удаления.
  • MVC Framework — веб-фреймворк Spring — это хорошо спроектированный веб-фреймворк MVC, который обеспечивает альтернативу таким веб-фреймворкам, как Struts или другим излишне спроектированным или менее популярным веб-фреймворкам.
  • Управление транзакциями — Spring имеет согласованный интерфейс управления транзакциями, который может масштабироваться до локальной транзакции (например, с использованием одной базы данных) или глобальных транзакций (например, с использованием JTA).
  • Обработка исключений — Spring предоставляет удобный API для преобразования исключений, связанных с конкретной технологией (например, вызванных JDBC, Hibernate или JDO) в согласованные, непроверенные исключения.

10. Что такое Spring beans?

Ответ: Spring beans — это экземпляры объектов, которыми управляет Spring Container. Они создаются и подключаются фреймворком и помещаются в «мешок объектов» (контейнер), откуда вы можете их позже извлечь. «Связка» (wiring) — это то, что является внедрением зависимостей. Это означает, что вы можете просто сказать: «Мне нужна эта вещь», и фреймворк будет следовать определенным правилам для получения этого объекта.

11. Какова цель модуля Core Container?

Ответ: Контейнер ядра обеспечивает основные функции платформы Spring. Первичным компонентом основного контейнера является BeanFactory — реализация шаблона Factory. BeanFactory применяет Инверсию управление для разделения конфигурации и зависимостей спецификации приложения от фактического кода приложения.

12. Что такое контекст приложения (Application Context)?

13. Как интегрировать Java Server Faces (JSF) с Spring?

Ответ: JSF и Spring действительно имеют одни и те же функции, особенно в области сервисов Инверсии управления. Объявляя управляемые компоненты JSF в файле конфигурации faces-config.xml, вы позволяете FacesServlet создавать экземпляр этого bean-компонента при запуске. Ваши страницы JSF имеют доступ к этим bean-компонентам и всем их свойствам. JSF и Spring можно интегрировать двумя способами: DelegatingVariableResolver : Spring поставляется с преобразователем переменных JSF, который позволяет вам использовать JSF и Spring вместе. DelegatingVariableResolver сначала делегирует поиск значений интерпретатору по умолчанию базовой реализации JSF, а затем — «бизнес-контексту» Spring WebApplicationContext. Это позволяет легко внедрять зависимости в JSF-управляемые компоненты. FacesContextUtils : настраиваемый VariableResolver хорошо работает при отображении своих свойств на bean-компоненты в faces-config.xml. Но если потребуется захватить bean-компонент, то класс FacesContextUtils это упрощает. Он похож на WebApplicationContextUtils, за исключением того, что принимает параметр FacesContext, а не параметр ServletContext.

14. Что такое Spring MVC framework?

Ответ: Инфраструктура Spring Web MVC предоставляет архитектуру model-view-controller и готовые компоненты, которые можно использовать для разработки гибких и слабосвязанных веб-приложений. Шаблон MVC приводит к разделению различных аспектов приложения (логика ввода, бизнес-логика и логика пользовательского интерфейса), обеспечивая при этом слабую связь между этими элементами.

15. Как происходит обработка событий в Spring?

Ответ: Обработка в ApplicationContext обеспечивается через ApplicationEvent класса и ApplicationListener интерфейса. То есть если bean-компонент реализует ApplicationListener, то каждый раз, когда ApplicationEvent публикуется в ApplicationContext, этот bean-компонент регистрируется. Спасибо за чтение и удачи в вашем техническом собеседовании!

Часть 3 - CMS GC и G1 GC

Сегодня мы продолжаем цикл статей о сборщиках мусора, поставляемых с виртуальной машиной Oracle Java HotSpot VM. Мы уже изучили немного теории и рассмотрели, каким образом с кучей расправляются два базовых сборщика — Serial GC и Parallel GC. А в этой статье речь пойдет о сборщиках CMS GC и G1 GC, первостепенной задачей которых является минимизация пауз при наведении порядка в памяти приложений, оперирующих средними и большими объемами данных, то есть по большей части в памяти серверных приложений.

Два этих сборщика объединяют общим названием «mostly concurrent collectors», то есть «по большей части конкурентные сборщики». Это связано с тем, что часть своей работы они выполняют параллельно с основными потоками приложения, то есть в какие-то моменты конкурируют с ними за ресурсы процессора. Конечно, это не проходит бесследно, и в итоге они разменивают улучшение в части пауз на ухудшение в части пропускной способности. Хотя делают это по-разному. Давайте посмотрим, как.

Использование CMS GC включается опцией -XX:+UseConcMarkSweepGC.

Принципы работы

Мы уже встречали слова Mark и Sweep при рассмотрении последовательного и параллельного сборщиков (если вы не встречали, то сейчас как раз самое время это сделать). Они обозначали два шага в процессе сборки мусора в старшем поколении: пометку выживших объектов и удаление мертвых объектов. Сборщик CMS получил свое название благодаря тому, что выполняет указанные шаги параллельно с работой основной программы.

При этом CMS GC использует ту же самую организацию памяти, что и уже рассмотренные Serial / Parallel GC: регионы Eden + Survivor 0 + Survivor 1 + Tenured и такие же принципы малой сборки мусора. Отличия начинаются только тогда, когда дело доходит до полной сборки. В случае CMS ее называют старшей (major) сборкой, а не полной, так как она не затрагивает объекты младшего поколения. В результате, малая и старшая сборки здесь всегда разделены. Одним из побочных эффектов такого разделения является то, что все объекты младшего поколения (даже потенциально мертвые) могут играть роль корней при определении статуса объектов в старшем поколении.

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

Давайте рассмотрим, что из себя представляет старшая сборка мусора при использовании CMS GC.

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

Естественно, за время такого поиска ситуация в куче может поменяться, и не вся информация, собранная во время поиска живых объектов, оказывается актуальной. Поэтому сборщик еще раз приостанавливает работу приложения и просматривает кучу для поиска живых объектов, ускользнувших от него за время первого прохода. При этом допускается, что в живые будут записаны объекты, которые на время окончания составления списка таковыми уже не являются. Эти объекты называются плавающим мусором (floating garbage), они будут удалены в процессе следующей сборки.

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

Потоки при работе сборщика CMS

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

Отдельно следует рассмотреть ситуацию, когда сборщик не успевает очистить Tenured до того момента, как память полностью заканчивается. В этом случае работа приложения останавливается, и вся сборка производится в последовательном режиме. Такая ситуация называется сбоем конкурентного режима (concurrent mode failure). Сборщик сообщает нам об этих сбоях при включенных опциях -verbose:gc или -Xloggc:filename.

У CMS есть один интересный режим работы, называемый Incremental Mode, или i-cms, который заставляет его временно останавливаться при выполнении работ параллельно с основным приложением, чтобы на короткие периоды высвобождать ресурсы процессора (что-то вроде АБС у автомобиля). Это может быть полезным на машинах с малым количеством ядер. Но данный режим уже помечен как не рекомендуемый к применению и может быть отключен в будущих релизах, поэтому подробно его разбирать не будем.

Ситуации STW

  • Малая сборка мусора. Эта пауза ничем не отличается от аналогичной паузы в Parallel GC.
  • Начальная фаза поиска живых объектов при старшей сборке (так называемая initial mark pause). Эта пауза обычно очень короткая.
  • Фаза дополнения набора живых объектов при старшей сборке (известная также как remark pause). Она обычно длиннее начальной фазы поиска.

Настройка

Так как подходы к организации памяти у CMS аналогичны используемым в Serial / Parallel GC, для него применимы те же опции определения размеров регионов кучи, а также опции автоматической подстройки под требуемые параметры производительности.

Обычно CMS, основываясь на собираемой статистике о поведении приложения, сам определяет, когда ему выполнять старшую сборку, но у него также есть порог наполненности региона Tenured, при достижении которого должна обязательно быть инициирована старшая сборка. Этот порог можно задать с помощью опции , значение указывается в процентах. Значение -1 (иногда устанавливается по умолчанию) указывает на отключение сборки по такому условию.

Достоинства и недостатки

Достоинством данного сборщика по сравнению с рассмотренными ранее Serial / Parallel GC является его ориентированность на минимизацию времен простоя, что является критическим фактором для многих приложений. Но для выполнения этой задачи приходится жертвовать ресурсами процессора и зачастую общей пропускной способностью.

Вспомним еще, что данный сборщик не уплотняет объекты в старшем поколении, что приводит к фрагментации Tenured. Этот факт в совокупности с наличием плавающего мусора приводит к необходимости выделять приложению (конкретно — старшему поколению) больше памяти, чем потребовалось бы для других сборщиков (Oracle советует на 20% больше).

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

Тем не менее, такой сборщик может подойти приложениям, использующим большой объем долгоживущих данных. В этом случае некоторые его недостатки нивелируются. Но в любом случае, не стоит принимать решение о его использовании пока вы не познакомились с еще одним сборщиком в обойме Java HotSpot VM.

Вот мы и добрались до последнего и наверняка самого интересного для многих сборщика мусора — G1 (что является сокращением от Garbage First). Интересен он прежде всего тем, что не является явным продолжением линейки Serial / Parallel / CMS, добавляющим параллельность еще в какую-нибудь фазу сборки мусора, а использует уже существенно отличающийся подход к задаче очистки памяти.

G1 — самый молодой в составе сборщиков мусора виртуальной машины HotSpot. Он изначально позиционировался как сборщик для приложений с большими кучами (от 4 ГБ и выше), для которых важно сохранять время отклика небольшим и предсказуемым, пусть даже за счет уменьшения пропускной способности. На этом поле он конкурировал с CMS GC, хотя изначально и не так успешно, как хотелось бы. Но постепенно он исправлялся, улучшался, стабилизировался и, наконец, достиг такого уровня, что Oracle говорит о нем как о долгосрочной замене CMS, а в Open JDK даже серьезно рассматривают его на роль сборщика по умолчанию для серверных конфигураций в 9-й версии.

Это все явно стоит того, чтобы разобраться с его устройством. Не будем же откладывать.

G1 включается опцией Java -XX:+UseG1GC.

Принципы работы

Первое, что бросается в глаза при рассмотрении G1 — это изменение подхода к организации кучи. Здесь память разбивается на множество регионов одинакового размера. Размер этих регионов зависит от общего размера кучи и по умолчанию выбирается так, чтобы их было не больше 2048, обычно получается от 1 до 32 МБ. Исключение составляют только так называемые громадные (humongous) регионы, которые создаются объединением обычных регионов для размещения очень больших объектов.

Разделение регионов на Eden, Survivor и Tenured в данном случае логическое, регионы одного поколения не обязаны идти подряд и даже могут менять свою принадлежность к тому или иному поколению. Пример разделения кучи на регионы может выглядеть следующим образом (количество регионов сильно приуменьшено):

Регионы сборщика G1 GC

Малые сборки выполняются периодически для очистки младшего поколения и переноса объектов в регионы Survivor, либо их повышения до старшего поколения с переносом в Tenured. Над переносом объектов трудятся несколько потоков, и на время этого процесса работа основного приложения останавливается. Это уже знакомый нам подход из рассмотренных ранее сборщиков, но отличие состоит в том, что очистка выполняется не на всем поколении, а только на части регионов, которые сборщик сможет очистить не превышая желаемого времени. При этом он выбирает для очистки те регионы, в которых, по его мнению, скопилось наибольшее количество мусора и очистка которых принесет наибольший результат. Отсюда как раз название Garbage First — мусор в первую очередь.

  1. Initial mark. Пометка корней (с остановкой основного приложения) с использованием информации, полученной из малых сборок.
  2. Concurrent marking. Пометка всех живых объектов в куче в нескольких потоках, параллельно с работой основного приложения.
  3. Remark. Дополнительный поиск не учтенных ранее живых объектов (с остановкой основного приложения).
  4. Cleanup. Очистка вспомогательных структур учета ссылок на объекты и поиск пустых регионов, которые уже можно использовать для размещения новых объектов. Первая часть этого шага выполняется при остановленном основном приложении.

После окончания цикла пометки G1 переключается на выполнение смешанных сборок. Это значит, что при каждой сборке к набору регионов младшего поколения, подлежащих очистке, добавляется некоторое количество регионов старшего поколения. Количество таких сборок и количество очищаемых регионов старшего поколения выбирается исходя из имеющейся у сборщика статистики о предыдущих сборках таким образом, чтобы не выходить за требуемое время сборки. Как только сборщик очистил достаточно памяти, он переключается обратно в режим малых сборок.

Очередной цикл пометки и, как следствие, очередные смешанные сборки будут запущены тогда, когда заполненность кучи превысит определенный порог.

Смешанная сборка мусора в приведенном выше примере кучи может пройти вот так:

Смешанная сборка в G1 GC

Может оказаться так, что в процессе очистки памяти в куче не остается свободных регионов, в которые можно было бы копировать выжившие объекты. Это приводит к возникновению ситуации allocation (evacuation) failure, подобие которой мы видели в CMS. В таком случае сборщик выполняет полную сборку мусора по всей куче при остановленных основных потоках приложения.

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

Гиганты

  • Он никогда не перемещается между регионами.
  • Он может удаляться в рамках цикла пометки или полной сборки мусора.
  • В регион, занятый громадным объектом, больше никого не подселяют, даже если в нем остается свободное место.

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

Ситуации STW

  1. Процессы переноса объектов между поколениями. Для минимизации таких пауз G1 использует несколько потоков.
  2. Короткая фаза начальной пометки корней в рамках цикла пометки.
  3. Более длинная пауза в конце фазы remark и в начале фазы cleanup цикла пометки.

Настройка

Так как основной целью сборщика G1 является минимизация пауз в работе основного приложения, то и главной опцией при его настройке можно считать уже встречавшуюся нам , задающую приемлемое для нас максимальное время разовой сборки мусора. Даже если вы не собираетесь задавать это свойство, хотя бы проверьте его значение по умолчанию. Хотя в документации Oracle и говориться, что по умолчанию время сборки не ограничено, но по факту это не всегда так.

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

Если вас не устраивает автоматический выбор размера региона, вы можете задать его вручную с помощью опции . Значение должно быть степенью двойки, если мерить в мегабайтах. Например, .

При желании можно изменить порог заполненности кучи, при достижении которого инициируется выполнение цикла пометок и переход в режим смешанных сборок. Это делается опцией , принимающей значение в процентах. По умолчанию, этот порог равен 45%.

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

Достоинства и недостатки

G1 Duke

В целом считается, что сборщик G1 более аккуратно предсказывает размеры пауз, чем CMS, и лучше распределяет сборки во времени, чтобы не допустить длительных остановок приложения, особенно при больших размерах кучи. При этом он лишен и некоторых других недостатков CMS, например, он не фрагментирует память.

Расплатой за достоинства G1 являются ресурсы процессора, которые он использует для выполнения достаточно большой части своей работы параллельно с основной программой. В результате страдает пропускная способность приложения. Целевым значением пропускной способности по умолчанию для G1 является 90%. Для Parallel GC, например, это значение равно 99%. Это, конечно, не значит, что пропускная способность с G1 всегда будет почти на 10% меньше, но данную особенность следует всегда иметь в виду.


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

Изучите основы различных механизмов сборки мусора JVM (GC) и вариантов использования.

1. Обзор

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

2. Краткое введение в сборку мусора

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

Проще говоря, GC работает в два простых шага, известных как Маркировка и развертка:

  • Нет ручной обработки выделения/освобождения памяти, поскольку неиспользуемое пространство памяти автоматически обрабатывается GC
  • Никаких накладных расходов на обработку Болтающийся указатель
  • Автоматическое управление утечкой памяти ( GC само по себе не может гарантировать полное решение проблемы утечки памяти, однако оно заботится о значительной ее части)
  • Поскольку JVM должен отслеживать создание/удаление ссылок на объекты, это действие требует большей мощности процессора, чем исходное приложение. Это может повлиять на производительность запросов, для которых требуется большая память
  • Программисты не контролируют планирование процессорного времени, выделенного на освобождение объектов, которые больше не нужны
  • Использование некоторых реализаций GC может привести к непредсказуемой остановке приложения
  • Автоматическое управление памятью не будет таким эффективным, как правильное ручное выделение/освобождение памяти

3. Реализация GC

JVM имеет четыре типа реализаций GC :

  • Последовательный Сборщик Мусора
  • Параллельный Сборщик Мусора
  • Сборщик мусора CMS
  • Сборщик мусора G1

3.1. Последовательный Сборщик Мусора

Это самая простая реализация GC, так как она в основном работает с одним потоком. В результате эта GC реализация замораживает все потоки приложения при запуске . Следовательно, не рекомендуется использовать его в многопоточных приложениях, таких как серверные среды.

Тем не менее, был отличный разговор от Twitter инженеров на QCon 2012 о производительности Последовательного сборщика мусора – что является хорошим способом лучше понять этот сборщик.

Последовательный GC является сборщиком мусора для большинства приложений, которые не имеют небольших требований к времени паузы и работают на машинах клиентского типа. Чтобы включить Последовательный сборщик мусора , мы можем использовать следующий аргумент:

3.2. Параллельный Сборщик Мусора

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

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

Количество потоков сборщика мусора можно контролировать с помощью параметра командной строки -XX:ParallelGCThreads= .

Цель максимального времени паузы (промежуток [в миллисекундах] между двумя GC )задается с помощью параметра командной строки -XX:MaxGCPauseMillis= .

Максимальная целевая пропускная способность (измеряемая в отношении времени, затраченного на сборку мусора, по сравнению со временем, затраченным вне сборки мусора) задается параметром командной строки -XX:GCTimeRatio=.

Максимальный объем памяти кучи (объем памяти кучи, необходимый программе во время работы) задается с помощью параметра -Xmx.

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

3.3. Сборщик мусора CMS

Реализация Concurrent Mark Sweep (CMS) использует несколько потоков сборщика мусора для сбора мусора. Он предназначен для приложений, которые предпочитают более короткие паузы в сборке мусора и могут позволить себе совместно использовать ресурсы процессора со сборщиком мусора во время работы приложения.

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

Здесь следует отметить, что, поскольку этот GC является параллельным, вызов явной сборки мусора, такой как использование System.gc() во время работы параллельного процесса, приведет к сбою |/параллельного режима/Прерыванию .

Если более 98% общего времени тратится на сборку мусора CMS и восстанавливается менее 2% кучи, то OutOfMemoryError выбрасывается CMS | сборщиком . При необходимости эту функцию можно отключить, добавив в командную строку параметр -XX:-UseGCOverheadLimit .

Этот коллектор также имеет режим, известный как инкрементный режим, который устарел в Java SE 8 и может быть удален в будущем крупном выпуске.

Чтобы включить сборщик мусора CMS , мы можем использовать следующий флаг:

Более того, Java 14 полностью отказался от поддержки CMS:

3.4. Сборщик мусора G1

Сборщик мусора G1 (Garbage First) предназначен для приложений, работающих на многопроцессорных машинах с большим объемом памяти. Он доступен с JDK 7 Update 4 и в более поздних выпусках.

G1 collector заменит CMS collector, так как он более эффективен с точки зрения производительности.

В отличие от других сборщиков, G1 сборщик разбивает кучу на набор областей кучи одинакового размера, каждая из которых представляет собой непрерывный диапазон виртуальной памяти. При выполнении сборки мусора G1 показывает параллельную глобальную фазу маркировки (т. Е. фазу 1, известную как Маркировка) для определения живучести объектов по всей куче.

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

3.5. Изменения в Java 8

Java 8u20 ввела еще один параметр JVM для уменьшения ненужного использования памяти путем создания слишком большого количества экземпляров одной и той же строки . Это оптимизирует память кучи, удаляя дубликаты String значений в глобальный одиночный char[] массив.

Этот параметр можно включить, добавив -XX:+UseStringDeduplication в качестве параметра JVM .

4. Заключение

В этом кратком руководстве мы рассмотрели различные реализации Сборки мусора JVM и их варианты использования.

Сборщик мусора Garbage-First (G1) предназначен для многопроцессорных машин с большим объемом памяти. Он с высокой вероятностью пытается достичь целей времени паузы при сборке мусора, одновременно обеспечивая высокую пропускную способность и не требуя настройки. G1 стремится обеспечить лучший баланс между задержкой и пропускной способностью, используя текущие целевые приложения и среды, функции которых включают:

  • Размеры кучи составляют до десятков ГБ или более, причем более 50% кучи Java занято живыми данными.
  • Темпы размещения объектов и продвижения, которые могут значительно меняться со временем.
  • Значительное количество фрагментации в куче.
  • Предсказуемые целевые значения времени паузы, которые не длиннее нескольких сотен миллисекунд, избегая длительных пауз сборки мусора.

G1 заменяет коллектор Concurrent Mark-Sweep (CMS). Это также сборщик по умолчанию.

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

Включение G1

Сборщик мусора Garbage-First является сборщиком по умолчанию, поэтому обычно вам не нужно выполнять никаких дополнительных действий. Вы можете явно включить его, указав -XX:+UseG1GC в командной строке.

Основные понятия

G1 - это работающий с поколениями объектов, инкрементный, параллельный, преимущественно конкурентный, "останавливающий мир" (stop-the-world) и эвакуационный сборщик мусора, который отслеживает цели времени паузы в каждой из остановок stop-the-world. Подобно другим сборщикам, G1 разделяет кучу на (виртуальное) молодое и старое поколения. Усилия по освоению пространства сосредоточены на молодом поколении там, где это наиболее эффективно, а в старшем поколении время от времени - на освоении пространства.

Некоторые операции всегда выполняются в паузах stop-the-world для повышения пропускной способности. Другие операции, которые занимают больше времени при остановке приложения, такие как операции с целой кучей, такие как глобальная маркировка, выполняются параллельно и конкурентно с приложением. Чтобы сделать короткие паузы stop-the-world короткими для регенерации пространства, G1 выполняет регенерацию пространства поэтапно, поэтапно и параллельно. G1 достигает предсказуемости, отслеживая информацию о предыдущем поведении приложения и паузах сбора мусора, чтобы построить модель связанных затрат. Он использует эту информацию для оценки работы, выполненной в паузах. Например, G1 сначала освобождает пространство в наиболее эффективных областях (то есть областях, которые в основном заполнены мусором, поэтому и называется Garbage-First (дословно Мусор-Первый) - из-за первоочередной работы с простраствами заполненными мусором).

G1 восстанавливает пространство в основном с помощью эвакуации: живые объекты, найденные в выбранных областях памяти для сбора, копируются в новые области памяти, сжимая их в процессе. После завершения эвакуации пространство, ранее занимаемое живыми объектами, повторно используется для распределения приложением.

Сборщик Garbage-First - это не сборщик в реальном времени. Он пытается достичь поставленных целей времени паузы с высокой вероятностью в течение более длительного времени, но не всегда с абсолютной уверенностью для данной паузы.

Разметка кучи

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


Молодое поколение содержит районы eden (красный) и районы выживших (survivor) (красный с "S"). Эти области обеспечивают ту же функцию, что и соответствующие смежные пространства в других коллекторах, с той разницей, что в G1 эти области обычно располагаются в виде непрерывного шаблона в памяти. Старые регионы (светло-голубые) составляют старое поколение. Области старого поколения могут быть огромными (светло-голубой с буквой "H") для объектов, которые охватывают несколько областей.

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

Цикл сбора мусора

На верхнем уровне коллектор G1 чередуется между двумя фазами. Фаза "только для молодых" содержит сборки мусора, которые постепенно заполняют доступную в настоящее время память объектами старого поколения. На этапе освоения пространства G1 постепенно восстанавливает пространство в старом поколении, в дополнение к работе с молодым поколением. Затем цикл возобновляется с фазы "только для молодых".


В следующем списке подробно описаны фазы, их паузы и переход между фазами цикла сборки мусора G1:

  1. Фаза "только для молодых": эта фаза начинается с нескольких обычных сборок молодых объектов, которые продвигают объекты в старое поколение. Переход между фазой "только для молодых" и фазой освоения пространства начинается, когда занятость старого поколения достигает определенного порогового значения, порогового значения Initiating Heap Occupancy. В это время G1 планирует Конкурентное начало молодой сборки вместо обычной молодой сборки.
    • Конкурентное начало (Concurrent Start): этот тип сборки запускает процесс маркировки в дополнение к выполнению обычной молодой сборки. Одновременная маркировка определяет все доступные в настоящее время (живые) объекты в регионах старого поколения, которые будут сохранены для следующей фазы освоения пространства. Хотя маркировка сборки еще не закончена, могут появиться обычные молодые сборки. Маркировка заканчивается двумя специальными паузами stop-the-world: Remark и Cleanup.
    • Примечание (Remark). Эта пауза завершает саму маркировку, выполняет глобальную обработку ссылок и выгрузку классов, восстанавливает полностью пустые области и очищает внутренние структуры данных. Между Remark и Cleanup G1 вычисляет информацию, чтобы впоследствии иметь возможность конкурентно освободить свободное место в выбранных областях старого поколения, что будет завершено в паузе Cleanup.
    • Очистка (Cleanup): эта пауза определяет, будет ли на самом деле фаза восстановления пространства. Если наступает этап освоения пространства, этап "только для молодых" завершается одной сборкой Prepare Mixed young.
  2. Этап восстановления пространства. Этот этап состоит из нескольких смешанных сборок, которые в дополнение к регионам молодого поколения также эвакуируют живые объекты из наборов областей старого поколения. Фаза восстановления пространства заканчивается, когда G1 определяет, что эвакуация большего количества областей старого поколения не даст достаточно свободного места, чтобы стоить усилий.

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

Паузы для сбора мусора и набор для сбора

G1 выполняет сборку мусора и восстановление пространства в паузах stop-the-world. Живые объекты обычно копируются из исходных областей в одну или несколько областей назначения в куче, и существующие ссылки на эти перемещенные объекты корректируются.

Для не-огромных (non-humongous) областей область назначения для объекта определяется из исходной области этого объекта:

  • Объекты молодого поколения (районы eden и survivor) копируются в survivor или старые регионы, в зависимости от их возраста.
  • Объекты из старых регионов копируются в другие старые регионы.
  • Объекты в огромных регионах обрабатываются по-разному. G1 только определяет их жизнеспособность, и, если они не живы, восстанавливает пространство, которое они занимают. Объекты в пределах огромных областей никогда не перемещаются G1.

Набор сбора - это набор исходных областей, из которых можно восстановить пространство. В зависимости от типа сборки мусора, набор сбора состоит из различных областей:

  • На этапе "только для молодых" набор сбора состоит только из областей молодого поколения и огромных областей с объектами, которые потенциально могут быть восстановлены.
  • На этапе "Восстановление пространства" набор сбора состоит из областей молодого поколения, огромных областей с объектами, которые потенциально могут быть восстановлены, и некоторых областей старого поколения из набора областей-кандидатов набора сбора.

G1 подготавливает набор регионов-кандидатов во время конкурентного цикла. Во время паузы Remark G1 выбирает регионы с низкой загруженностью, которые являются областями, которые содержат значительное количество свободного пространства. Затем эти области подготавливаются одновременно между паузами Remark и Cleanup для последующего сбора. Пауза очистки сортирует результаты этой подготовки в соответствии с их эффективностью. Более эффективные регионы, которые, по-видимому, занимают меньше времени для сбора и содержат больше свободного пространства, предпочтительнее в последующих смешанных сборках.

Читайте также: