Рубрики
Без рубрики

Управление памятью в Java Вопросы интервью (+Ответы)

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

Автор оригинала: baeldung.

1. введение

В этой статье мы рассмотрим некоторые вопросы управления памятью, которые часто возникают во время интервью с разработчиками Java. Управление памятью-это область, с которой не так много разработчиков знакомы.

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

С другой стороны, эти концепции на самом деле довольно распространены в интервью, так что давайте сразу перейдем к делу.

2. Вопросы

Q1. Что означает утверждение “Память управляется в Java”?

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

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

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

Q2. Что такое Сбор мусора и каковы Его Преимущества?

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

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

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

Q3. Существуют ли какие-либо недостатки Сбора мусора?

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

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

В4. Что означает термин “Остановить мир”?

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

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

Q5. Что такое Стек и куча? Что хранится в каждой из Этих Структур Памяти и как Они Взаимосвязаны?

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

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

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

Q6. Что такое Сбор мусора поколений и что делает Его Популярным Подходом к сбору мусора?

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

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

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

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

Сегодня почти все сборщики мусора являются поколениями. Эта стратегия настолько популярна, потому что со временем она оказалась оптимальным решением.

Q7. Подробно Опишите, Как Работает Сбор Мусора Поколений

Чтобы правильно понять, как работает сбор мусора поколений, важно сначала вспомнить, как структурирована куча Java , чтобы облегчить сбор мусора поколений.

Куча делится на меньшие пространства или поколения. Эти пространства-Молодое поколение, Старое или Арендованное Поколение и Постоянное Поколение.

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

Термин “возраст” в поколенческой сборке мусора относится к числу циклов сбора, которые пережил объект .

Пространство молодого поколения далее разделено на три пространства: пространство Эдема и два пространства выживших, таких как Выживший 1 (s1) и Выживший 2 (s2).

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

постоянное поколение или более часто называемое PermGen, содержит метаданные, необходимые JVM для описания классов и методов, используемых в приложении. Он также содержит пул строк для хранения интернированных строк. Он заполняется JVM во время выполнения на основе классов, используемых приложением. Кроме того, здесь могут храниться классы и методы библиотеки платформы.

Во-первых, любые новые объекты выделяются в пространство Eden . Оба места для выживших начинаются пустыми. Когда пространство Эдема заполняется, запускается незначительная сборка мусора. Объекты, на которые ссылаются ссылки, перемещаются в первое оставшееся в живых пространство. Объекты без ссылок удаляются.

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

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

На следующем незначительном GC повторяется тот же процесс. Однако на этот раз выживший переключается. Объекты, на которые ссылаются ссылки, перемещаются в S1 как из Eden, так и из S2. Выжившие объекты стареют. Эдем и S2 очищены.

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

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

Q8. Когда Объект становится Пригодным для сбора мусора? Опишите, Как Гк Собирает Подходящий объект?

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

Самый простой случай, когда объект становится пригодным для сборки мусора, – это если все его ссылки равны нулю. Циклические зависимости без какой-либо живой внешней ссылки также имеют право на GC. Таким образом, если объект A ссылается на объект B и объект B ссылается на объект A, и у них нет другой живой ссылки, то оба объекта A и B будут иметь право на сборку мусора.

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

Q9. Как Вы запускаете сборку мусора из кода Java?

Вы, как Java-программист, не можете принудительно собирать мусор в Java ; он будет срабатывать только в том случае, если JVM считает, что ему нужна сборка мусора на основе размера кучи Java.

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

Кроме того, существуют такие методы, как System.gc() и Runtime.gc (), которые используются для отправки запроса на сборку мусора в JVM, но не гарантируется, что сбор мусора произойдет.

Q10. Что происходит, когда Не хватает места в куче для хранения новых объектов?

Если нет места в памяти для создания нового объекта в куче, виртуальная машина Java выдает OutOfMemoryError или, более конкретно, |/java.lang.OutOfMemoryError пространство кучи.

Q11. Можно ли «Воскресить» Объект, который стал Пригодным для сбора мусора?

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

В методе finalize вы можете технически “воскресить” объект, например, назначив его статическому полю. Объект снова станет живым и не будет подлежать сборке мусора, поэтому GC не будет собирать его в течение следующего цикла.

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

Q12. Опишите Сильные, Слабые, Мягкие и Фантомные ссылки и их Роль в сборке мусора.

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

Java предоставляет нам ссылочные объекты для управления отношениями между объектами, которые мы создаем, и сборщиком мусора.

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

StringBuilder sb = new StringBuilder();

В приведенном выше фрагменте ключевое слово new создает новый объект StringBuilder и сохраняет его в куче. Переменная sb затем сохраняет сильную ссылку на этот объект. Что это означает для сборщика мусора, так это то, что конкретный объект StringBuilder вообще не подходит для сбора из-за сильной ссылки на него sb . История меняется только тогда, когда мы аннулируем sb вот так:

sb = null;

После вызова приведенной выше строки объект будет иметь право на сбор.

Мы можем изменить эту связь между объектом и сборщиком мусора, явно обернув его внутри другого ссылочного объекта, который находится внутри java.lang.ref package.

Мягкая ссылка может быть создана для вышеуказанного объекта следующим образом:

StringBuilder sb = new StringBuilder();
SoftReference sbRef = new SoftReference<>(sb);
sb = null;

В приведенном выше фрагменте мы создали две ссылки на объект StringBuilder . Первая строка создает сильную ссылку |/sb , а вторая строка создает мягкую ссылку | краткое описание . Третья строка должна сделать объект пригодным для сбора, но сборщик мусора отложит его сбор из-за sbRef .

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

слабая ссылка может быть создана аналогичным образом с помощью класса WeakReference . Когда sb имеет значение null, а объект StringBuilder имеет только слабую ссылку, сборщик мусора JVM не будет иметь абсолютно никаких компромиссов и немедленно соберет объект в самом следующем цикле.

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

Q13. Предположим, Что У Нас Есть Круговая ссылка (Два Объекта, Которые Ссылаются Друг На Друга). Может ли такая пара объектов Стать Подходящей для сбора мусора и почему?

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

Q14. Как строки представлены в памяти?

Экземпляр String в Java-это объект с двумя полями: значением char [] field и хэшем int field. Поле value представляет собой массив символов, представляющих саму строку, а поле hash содержит hashCode строки, которая инициализируется нулем, вычисляется во время первого вызова hashCode() и с тех пор кэшируется. Как любопытный крайний случай, если Хэш-код строки имеет нулевое значение, его необходимо пересчитывать каждый раз, когда вызывается hashCode () .

Важно то, что экземпляр String является неизменяемым: вы не можете получить или изменить базовый массив char [] . Еще одной особенностью строк является то, что статические постоянные строки загружаются и кэшируются в пуле строк. Если у вас есть несколько идентичных String объектов в исходном коде, все они представлены одним экземпляром во время выполнения.

Q15. Что такое Stringbuilder и каковы его варианты использования? В чем разница между добавлением строки в Stringbuilder и объединением двух строк с помощью оператора+? Чем Stringbuilder отличается от Stringbuffer?

StringBuilder позволяет манипулировать последовательностями символов путем добавления, удаления и вставки символов и строк. Это изменяемая структура данных, в отличие от класса String , который является неизменяемым.

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

StringBuffer отличается от StringBuilder тем, что он потокобезопасен. Если вам нужно манипулировать строкой в одном потоке, вместо этого используйте StringBuilder .

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

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

Это следует рассматривать не как исчерпывающий список вопросов, а скорее как стартовую площадку для дальнейших исследований. Мы, в Baeldung, желаем вам успехов в любых предстоящих интервью.