JavaRush/Java блог/Java Developer/Ещё о сборщике мусора в Java
Автор
Milan Vucic
Репетитор по программированию в Codementor.io

Ещё о сборщике мусора в Java

Статья из группы Java Developer
участников
Привет! В прошлой лекции мы впервые познакомились со встроенным механизмом языка Java — сборщиком мусора. Он функционирует в фоновом режиме во время работы твоей программы, собирает ставшие ненужными объекты, которые в дальнейшем будут удалены. Таким образом, он освобождает память для создания новых объектов в будущем. В этой лекции мы подробнее разберем принцип его работы. Например, как и в какой момент объект становится ненужным? И как об этом узнает сборщик мусора? На эти вопросы и ответим :) Лекция у нас скорее обзорная: этот материал не надо заучивать наизусть. Он призван скорее расширить твой кругозор касаемо работы памяти и сборщика мусора, поэтому будет достаточно прочесть его и вынести что-то новое для себя :) Поехали! Первое, о чем тебе нужно помнить — сборщик мусора работает параллельно с твоей программой. Он не является ее частью и функционирует отдельно: для описания этого мы в прошлой лекции приводили аналогию с роботом-пылесосом. На самом деле, так было не всегда. Раньше сборщик мусора был устроен таким образом, что работал в одном потоке с твоей программой. И по какому-то графику, раз в сколько-то минут, начинал проверку на наличие в программе ненужных объектов. Проблема заключалась в том, что на время этой проверки и сборки мусора программа зависала и не выполнялась. Представь, что ты сидишь в офисе за работой. Но тут приходит уборщица, которой нужно вымыть полы в помещении. Она выгоняет тебя из-за компьютера на 5 минут и ты ждешь, пока она не закончит уборку. В это время ты работать не можешь. Вот примерно так раньше работали сборщики мусора :) Позднее этот механизм изменили, и теперь сборщик мусора работает в фоновом режиме, не тормозя работу самой программы. Ты уже знаешь, что объект умирает, когда на него не остается ни одной ссылки. Но на самом деле сборщик мусора не считает ссылки на объекты. Во-первых, это может быть достаточно долго. Во-вторых, не очень эффективно. Ведь объекты могут ссылаться друг на друга! Ещё о сборщике мусора  - 2На рисунке изображен пример, когда 3 объекта ссылаются друг на друга, но больше на них не ссылается никто. То есть для работы остальной части программы они не нужны. Если бы сборщик мусора занимался просто подсчетом ссылок, все эти 3 объекта остались и не освободили бы память: ссылки-то на них есть! Это можно сравнить с космическим кораблем. Космонавты во время полета решили проверить список запчастей для ремонта и обнаружили среди них руль и педали от обычного автомобиля. Они явно тут не нужны и занимают лишнее место. Хоть эти детали связаны и имеют какие-то функции, в рамках работы космического корабля это ненужный мусор, от которого лучше избавиться. Поэтому в Java приняли решение сделать основой для сборки мусора не подсчет ссылок, а разделение объектов на два вида — достижимые и недостижимые. Как определить, является ли объект достижимым? Все гениальное просто. Объект считается достижимым, если на него ссылается другой достижимый объект. Получается такая “цепочка достижимости”. Она начинается при запуске программы и тянется в течение всего времени ее работы. Это выглядит примерно вот так: Ещё о сборщике мусора  - 4Стрелка на рисунке обозначает выполняемый код нашей программы. В коде, например, в методе main(), создаются ссылки на объекты. Эти объекты могут ссылаться на новые объекты, те — еще на какие-то и так далее. Образуется цепочка ссылок объектов. Если от объекта по этой цепочке ссылок можно прийти к “корневой ссылке”, то есть той, которая непосредственно создается в выполняемом коде, — он считается достижимым. У нас на картинке они обозначены синим цветом. А вот если объект выпал из этой цепочки, то есть ни одна из переменных в коде, выполняемом в данный момент, не содержит ссылок на него, и по “цепочке ссылок” до него тоже невозможно добраться — он считается недостижимым. В нашей программе два таких объекта обозначены красным цветом. Обрати внимание: у этих “красных” объектов есть ссылки друг на друга. Но, как мы и сказали ранее, современный сборщик мусора в Java не занимается подсчетом ссылок. Он определяет достижимость либо недостижимость объекта. Поэтому два красных объекта на рисунке станут его добычей. Теперь рассмотрим весь процесс от начала до конца, а заодно посмотрим, как устроена память в Java :) Все объекты в Java хранятся в специальной области памяти, которая называется куча (heap). В обычном языке “кучей” называют гору предметов, где все подряд валяется вперемешку. Но куча в Java не такая. Она имеет очень логичную и разумную структуру. В один прекрасный день программисты Java обнаружили, что все объекты в их программах можно разделить на два типа — условно говоря, простые объекты и “долгожители”. “Долгожителями” считаются объекты, пережившие много сборок мусора. Чаще всего они будут существовать до конца работы программы. В итоге общая куча, где хранятся все созданные объекты, была разделена на несколько частей. Первая часть имеет красивое название — Eden (библ. “Райский сад”). Это отличное название, ведь именно сюда объекты попадают после их создания. Именно в этой части выделяется память для новых объектов, когда мы пишем new. Объектов может создаться много, и когда в этой области заканчивается место, начинается первая, “быстрая” сборка мусора. Надо сказать, что сборщик мусора очень умен и выбирает алгоритм работы в зависимости от того, чего в куче больше — мусора или рабочих объектов. Если почти все объекты являются мусором, сборщик помечает “живые” объекты и переносит их в другую область памяти, после чего текущая область очищается полностью. Если же мусора мало и большую часть занимают живые объекты, он помечает мусор, очищает его, а остальные объекты компонует. Мы сказали “сборщик помечает “живые” объекты и переносит их в другую область памяти”, но в какую? Область памяти, куда переносятся все объекты, пережившие хотя бы одну сборку мусора, называется Survival Space (“место для выживших”). Survival Space в свою очередь делится на поколения. Каждый объект относится к своему поколению в зависимости от того, сколько сборок мусора он пережил. Если одну — он относится к “Поколению 1”, если 5 — к “Поколению 5”. Вместе Eden и Survival Space образуют область под названием Young Generation (“молодое поколение”). Помимо Young Generation в куче существует и другая область памяти — Old Generation (“старое поколение”). Сюда как раз попадают те самые объекты-долгожители, которые пережили много сборок мусора. Их выгоднее хранить отдельно от всех остальных. И только когда область Old Generation заполнена, т.е. даже объектов-долгожителей в программе так много, что памяти не хватает, производится полная уборка мусора. Она обрабатывает не одну область памяти, а вообще все созданные Java-машиной объекты. Естественно, она занимает куда больше времени и ресурсов. Именно поэтому объекты-долгожители было решено хранить отдельно. Когда место заканчивается в других областях, проводится так называемая “быстрая сборка мусора”. Она охватывает только одну область, и за счет этого является более экономичной и быстрой. В конце, когда забита уже даже область для долгожителей, в бой вступает полная уборка. Таким образом, самый “тяжеловесный” инструмент используется сборщиком только тогда, когда без этого уже не обойтись. Схематично структура кучи и уборки выглядят так: Ещё о сборщике мусора  - 5
Комментарии (171)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Сергей Титов
Уровень 24
10 апреля, 15:00
Райский сад - опасное место!
{Java_Shark}
Уровень 19
2 марта, 11:52
дедовщина какая-то в памяти)))
Denis Gritsay
Уровень 38
10 сентября 2023, 11:26
то есть обьекты в ходе уборки мусора постепенно перемещаются и затем попадают в old, из которой их убирают только после переполнения этой области памяти.
Novikova Natalia
Уровень 28
7 ноября 2023, 19:02
интересно, а как принимается решение , какие объекты убрать, если, допустим, они там все старые, но достижимые? Но память в этой области переполнена. Разработчик должен принять решение , какие объекты убрать, или можно например почистить "кэш" у этих объектов?
Denis Gritsay
Уровень 38
8 ноября 2023, 07:59
думаю старые но достижимые это врят ли
Алексей Backend Developer Expert
5 февраля, 11:33
Добрый день Наталия! Нет, разработчик не принимает решения, что оставить а что удалить! И у объектов нет "кэша". В этом случае разработчик начинает разбираться, а по какой причине так произошло, что память переполнена и что он мог сделать не так, что привело к этому.
Алексей Backend Developer Expert
5 февраля, 11:39
Добрый день Денис! Думаю в описАлись в фразе "думаю старые но достижимые это врят ли", ибо в статье разъясняется, что именно область памяти для "Старых" объеков помещаются те объекты, которые будут жить до конца работы программы (предположительно). Пример: Такие как объекты "Контроллеры" в приложениях типа "MVC".
Novikova Natalia
Уровень 28
9 февраля, 10:24
спасибо, Алексей!
Anatoly Enterprise Java Developer
28 августа 2023, 05:57
nice
Kiriall
Уровень 12
19 июня 2023, 06:03
Очень интересно и логично) Один только момент не понял про чистку Eden. Сказано, что там 2 алгоритма работы, и ,например, если мусора меньше, то он помечается и удаляется из этой области, а оставшиеся живые объекты компонуются. А потом говорится про Survival Space "куда переносятся все объекты, пережившие хотя бы одну сборку мусора". Так получается, что всегда "живые" объекты после чистки из Eden переносятся в Survival Space независимо от алгоритма чистки Eden, или только про чистке по алгоритму "мусора больше"?
Кот
Уровень 27
5 июля 2023, 14:06
Могу предположить, что живые объекты переносятся в Survival Space только после заполнения Eden-a и проведения первой, "быстрой чистки".
Ислам
Уровень 33
26 мая 2023, 15:06
Очень интересная лекция
IrinaVyu
Уровень 22
6 мая 2023, 18:53
отличная статья. у этого автора все статьи хороши,кстати говоря
Антон Кулаков
Уровень 20
11 мая 2023, 07:34
Согласен, всегда отличные статьи от автора 👍
17 апреля 2023, 14:04
Что будет если объект станет мусором в 3-м поколении, он все равно доживет до Old Generation? Как работает сборщик мусора в Survival Space? Хорошая статья, спасибо!
Станислав
Уровень 20
1 апреля 2023, 17:04
Супер!
Timur Khasmamedov
Уровень 14
Expert
30 января 2023, 20:15
Статья крутая. Прямо очень наглядно и полезно.