Анализ общих вопросов интервью JVM

Java

предисловие

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

1. При каких обстоятельствах произойдет переполнение памяти стека.

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

мой ответ:

  • Стек является частным для потока, и его жизненный цикл такой же, как и у потока.При выполнении каждого метода создается кадр стека для хранения таблицы локальных переменных, стека операндов, динамической ссылки, выхода метода и другой информации. . Таблица локальных переменных также содержит основные типы данных, типы ссылок на объекты
  • Если глубина стека, запрошенная потоком, больше максимальной глубины, разрешенной виртуальной машиной, будет выдано исключение StackOverflowError, и вызов рекурсивного метода даст этот результат.
  • Если стек виртуальной машины Java может быть динамически расширен, и действие расширения было предпринято, но не может быть применено для достаточного объема памяти для завершения расширения или недостаточно памяти для создания соответствующего стека виртуальной машины при создании нового потока, затем виртуальная машина Java Машина выдаст исключение OutOfMemory. (Запущено слишком много потоков)
  • Параметр -Xss для настройки размера стека JVM.

2. Подробно объясните модель памяти JVM

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

мой ответ:

  • Структура памяти JVM

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

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

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

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

Область метода: хранит загруженную информацию о классе, константы, статические переменные, данные кода, скомпилированные компилятором «точно в срок» и т. д. (т.е. постоянная полоса), целью рециркуляции в основном является рециркуляция постоянного пула и выгрузка типа, разделяемого каждым потоком

3. Почему память JVM делится на новое поколение, старое поколение и постоянное поколение. Почему новое поколение делится на Эдема и Выжившего.

Идеи:Поговорим о куче JAVA, делении нового поколения, а потом поговорим о преобразовании между ними, и настройке некоторых параметров между ними (таких как: –XX:NewRatio, –XX:SurvivorRatio и т.д.), и тогда поясните зачем нужно это деление.Лучше добавить свое понимание.

мой ответ:

1) Разделение области общей памяти

  • Общая область памяти = постоянный диапазон + куча

  • Постоянная полоса = область метода + другое

  • Куча Java = старое поколение + молодое поколение

  • Молодое поколение = Эдем + S0 + S1

2) Конфигурация некоторых параметров

  • По умолчанию соотношение молодого поколения (Young) к старому поколению (Old) составляет 1:2, что можно настроить параметром –XX:NewRatio.
  • По умолчанию Edem : from : to = 8 : 1 : 1 (можно задать параметром –XX:SurvivorRatio)
  • Количество копий объекта в области Survivor равно 15 (соответствует параметру виртуальной машины -XX:+MaxTenuringThreshold).

3) Почему он разделен на Eden и Survivor, зачем создавать две области Survivor?

  • Если выжившего нет, каждый раз, когда в районе Эдема выполняется Minor GC, уцелевшие объекты будут отправляться в старое поколение. Старое поколение быстро заполняется, запуская Major GC.Объем памяти старого поколения намного больше, чем у молодого поколения, а Full GC занимает намного больше времени, чем Minor GC, поэтому его нужно разделить на Eden и Выживший.
  • Значение существования Survivor заключается в том, чтобы уменьшить количество объектов, отправляемых в старое поколение, тем самым уменьшая возникновение полного GC.Предварительный просмотр Survivor гарантирует, что будут отправлены только объекты, которые могут выжить в новом поколении после 16 Minor GC. старому поколению. лет.
  • Самым большим преимуществом установки двух областей Survivor является решение проблемы фрагментации.Вновь созданный объект находится в Eden.После Minor GC,выжившие объекты в Eden будут перемещены в первую область Survivor S0,и Eden будет опустошен;ждите Eden Когда область будет заполнена, снова будет запущен Minor GC, а уцелевшие объекты в Эдеме и S0 будут скопированы и отправлены во второе пространство выживших S1 (этот процесс очень важен, потому что этот алгоритм копирования гарантирует, что объекты в S1 происходят из S0 и Eden. Две части выживших объектов занимают непрерывное пространство памяти, чтобы избежать фрагментации)

4. Что такое полный процесс GC в JVM и как объекты продвигаются до старости

Идеи:Чтобы описать разделение памяти кучи Java, объясните Minor GC, Major GC, full GC, описав процесс преобразования между ними.

мой ответ:

  • Куча Java = старое поколение + молодое поколение
  • Молодое поколение = Эдем + S0 + S1
  • Когда пространство в области Эдема заполнено, виртуальная машина Java запускает Minor GC для сбора мусора нового поколения, а уцелевшие объекты будут перемещены в область Survivor.
  • большой объект(объекты Java, требующие много непрерывного пространства памяти, например длинные строки)идти прямо к старости;
  • Если объект родился в Эдеме и выжил после первого Малого GC и был размещен у Выжившего, возраст устанавливается равным 1, а возраст +1 за каждый выживший Малый GC.Если возраст превышает определенный предел (15 лет), он переходит в старое состояние.. которыйСубъекты-долгожители вступают в состояние старости.
  • старость полнане может содержать больше объектов, После Minor GC обычно следует Full GC, Full GC очищает всю кучу памяти —В том числе молодое и старшее поколение.
  • Major GC ГК в старом поколении,Очистите участки для пожилых людей, часто сопровождаемый хотя бы одним второстепенным GC,Более чем в 10 раз медленнее, чем Minor GC.

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

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

мой ответ:

1) Несколько сборщиков мусора:

  • Серийный коллектор:Однопоточный сборщик при сборе мусора должен останавливать мир и использовать алгоритм копирования.
  • Коллекционер ParNew:Многопоточная версия сборщика Serial также должна останавливать мир и копировать алгоритм.
  • Параллельный сборщик мусора:Сборщик нового поколения, сборщик алгоритма репликации, параллельный многопоточный сборщик, целью которого является достижение контролируемой пропускной способности. Если виртуальная машина работает в общей сложности 100 минут, из которых 1 минута потрачена на мусор, пропускная способность составляет 99%.
  • Серийный Старый коллекционер:Является более старой версией сборщика Serial, однопоточного сборщика, использующего алгоритм маркировки для сопоставления.
  • Параллельный старый коллектор:Является более старой версией сборщика Parallel Scavenge, использующей многопоточный алгоритм пометки и сортировки.
  • Сборщик CMS (Concurrent Mark Sweep):является коллектором с целью получения кратчайшего времени перерыва в переработке,Алгоритм развертки пометки, рабочий процесс: начальная метка, параллельная маркировка, примечание, параллельная развертка, конец коллекции будет генерировать много космического мусора.
  • Коллектор G1:Реализация алгоритма сортировки тегов,Процесс работы в основном включает в себя следующее: начальная метка, параллельная метка, конечная метка, метка фильтра.. Никакой космический мусор не создается, и киоски можно точно контролировать.

2) Разница между сборщиком CMS и сборщиком G1:

  • Сборщик CMS является сборщиком старого поколения и может использоваться вместе с коллекторами Serial и ParNew нового поколения;
  • Диапазон сбора коллектора G1 - это старое поколение и новое поколение, и его не нужно использовать вместе с другими коллекторами;
  • Коллекторы CMS, которые стремятся к минимальному времени паузы;
  • Сборщик G1 предсказывает время паузы при сборке мусора
  • Сборщик CMS использует для сборки мусора алгоритм «пометки-очистки», который подвержен фрагментации памяти.
  • Сборщик G1 использует алгоритм «пометки для сортировки», который выполняет интеграцию пространства и уменьшает фрагментацию пространства памяти.

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

Идеи:Сначала нарисуйте диаграмму модели памяти Java в сочетании с примером volatile, чтобы объяснить, что такое переупорядочивание и барьеры памяти, и лучше всего написать следующую демонстрацию для интервьюера.

мой ответ:

1) Схема модели памяти Java:

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

2) Переупорядочивание инструкций.

Вот, сначала посмотрите на кусок кода

public class PossibleReordering {
static int x = 0, y = 0;
static int a = 0, b = 0;

public static void main(String[] args) throws InterruptedException {
    Thread one = new Thread(new Runnable() {
        public void run() {
            a = 1;
            x = b;
        }
    });

    Thread other = new Thread(new Runnable() {
        public void run() {
            b = 1;
            y = a;
        }
    });
    one.start();other.start();
    one.join();other.join();
    System.out.println(“(” + x + “,” + y + “)”);
}

Результатом операции может быть (1,0), (0,1) или (1,1) или (0,0). Потому что в реальном времени выполнения инструкции кода могут выполняться не строго в порядке операторов кода. Большинство современных микропроцессоров будут использовать метод выполнения не по порядку (OoOE или OOE), и, когда позволяют условия, непосредственно запускать последующие инструкции, которые в настоящее время могут выполняться немедленно, избегая выборки ожидания 3 для данных, требуемых следующей инструкцией. Благодаря технологии выполнения вне очереди процессор может значительно повысить эффективность выполнения. А этоперестановка инструкций.

3) Барьеры памяти

барьер памяти, также называемая забором памяти, — это инструкция ЦП, которая контролирует проблемы переупорядочения и видимости памяти при определенных условиях.

  • Загрузить барьер: Для таких операторов load1; loadload; load2, перед чтением данных в LOAD2 и последующими операциями чтения, данные, которые должны быть прочитаны, считываются перед доступом.
  • МагазинМагазин Барьер: Для такого оператора Store1; StoreStore; Store2 до выполнения операций Store2 и последующих операций записи операции записи Store1 гарантированно будут видны другим процессорам.
  • Барьер LoadStore: Для такого оператора Load1; LoadStore; Store2, прежде чем Store2 и последующие операции записи будут очищены, убедитесь, что данные, которые должны быть прочитаны Load1, были прочитаны.
  • Барьер StoreLoad: Для инструкции Store1; StoreLoad; Load2 записи Store1 гарантированно будут видны всем процессорам до выполнения Load2 и всех последующих операций чтения. Его накладные расходы - самый большой из четырех барьеров. В большинстве реализаций процессоров этот барьер является универсальным барьером, выполняющим функции трех других барьеров памяти.

4) принцип «случается раньше»

  • Однопоточный принцип «случается до»: В этом же потоке напишите операцию после того, как предыдущая операция произойдет раньше. Принцип работы замков «происходит до»: операция отпирания того же замка происходит до срабатывания блокировки этого замка.
  • Принцип «произошло до» изменчивости: Операция записи в volatile переменную происходит до любой операции над этой переменной (включая операции записи, конечно).
  • принцип транзитивности: Если A E работает, операция произойдет - до B, B Операция операции произойдет - до C, то A действует операция - до C.
  • Принцип «произошло до» запуска потока: Метод запуска этого же потока происходит раньше других методов этого потока.
  • Принцип «произошло до» прерывания потока: Вызов метода прерывания потока происходит до кода, обнаруживающего прерывание, отправленное прерванным потоком.
  • Принцип «случиться до» завершения потока:Все операции в потоке происходят до обнаружения завершения потока.
  • Принцип «произошло до» создания объекта:Инициализация объекта выполняется до вызова его метода finalize.

7. Кратко расскажите об известном вам загрузчике классов, может ли он сломать родительское делегирование и как это сломать.

Идеи:Сначала объясните, что такое загрузчик классов, можно нарисовать картинку для интервьюера, рассказать о смысле существования загрузчика классов, рассказать о модели родительского делегирования и, наконец, объяснить, как сломать модель родительского делегирования.

мой ответ:

1) Что такое загрузчик классов?

Классовой погрузчикЭто загрузка файла класса в память JVM в соответствии с указанным полным именем и преобразование его в объект класса.

  • Bootstrap ClassLoader: реализован на языке C++ (для HotSpot), он отвечает за загрузку в память библиотеки классов, хранящейся в каталоге \lib или пути, указанном параметром -Xbootclasspath.
  • Другие загрузчики классов: реализованы языком Java, унаследованы от абстрактного класса ClassLoader. как:
  • Расширение ClassLoader: отвечает за загрузку всех библиотек классов в каталог \lib\ext или путь, указанный в системной переменной java.ext.dirs.
  • Загрузчик классов приложений (Application ClassLoader). Отвечая за загрузку указанной библиотеки классов в пути к классам пользователя (classpath), мы можем использовать этот загрузчик классов напрямую. В общем, если у нас нет пользовательского загрузчика классов, этот загрузчик используется по умолчанию.

2) Модель родительского делегирования

Рабочий процесс родительской модели делегирования:

Если загрузчик класса получает запрос на загрузку класса, он не будет пытаться загрузить сам класс в первую очередь, а делегирует запрос загрузчику родительского класса. Это верно для каждого загрузчика классов, только если родительский загрузчик не может найти указанный класс в своей области поиска (например, ClassNotFoundException), дочерний загрузчик попытается загрузить его сам.

Схема модели родительского делегирования:

3) Зачем нужна родительская модель делегирования?

Здесь сначала подумайте, если нет родительского делегирования, то может ли пользовательОпределите класс с тем же именем, что и java.lang.Object.,Класс с тем же именем, что и java.lang.String, и поместите его в ClassPath, затемРезультаты сравнения между классами и уникальность классов не гарантируются, так зачем вам модель родительского делегирования?Предотвращение появления в памяти нескольких копий одного и того же байт-кода

4) Как сломать модель родительского делегирования?

Нарушение механизма родительского делегирования не толькоНаследовать ClassLoaderкласс, но иПереопределить loadClass и findClassметод.

8. Расскажите об основных параметрах JVM, которые вы знаете

Идеи:Мы можем говорить о конфигурации стека, сборщике мусора и вспомогательной информации.

мой ответ:

1) Конфигурация стека

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k 
-XX:MaxPermSize=16m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=0

-Хмх3550м:Максимальный размер кучи составляет 3550 м.

-Xms3550м:Установите начальный размер кучи на 3550 м.

-Xmn2g:Установите размер молодого поколения на 2g.

-Xss128k:Размер стека на поток составляет 128 КБ.

-XX:МаксПермСизе:Установите постоянный размер генерации на 16 м

-XX:NewRatio=4:Установите соотношение молодого поколения (включая Эдем и два региона Выживших) к старому поколению (исключая постоянное поколение).

-XX:Коэффициент выживания=4:Устанавливает соотношение размеров области Эдема к области Выживших в молодом поколении. Если установлено значение 4, соотношение двух областей Выживших к одной области Эдема составляет 2:4, а на одну область Выживших приходится 1/6 всего молодого поколения.

-XX:MaxTenuringThreshold=0:Установить максимальный возраст мусора. Если установлено значение 0, объекты молодого поколения напрямую входят в старое поколение, не проходя через область Survivor.

2) Сборщик мусора

-XX:+UseParallelGC
-XX:ParallelGCThreads=20
-XX:+UseConcMarkSweepGC 
-XX:CMSFullGCsBeforeCompaction=5
-XX:+UseCMSCompactAtFullCollection:

-XX:+UseParallelGC:Выберите сборщик мусора в качестве параллельного сборщика.

-XX:ParallelGCThreads=20:Настройте количество потоков для параллельного сборщика

-XX:+UseConcMarkSweepGC:Настройте одновременную сборку для старого поколения.

-XX:CMSFullGCsBeforeCompaction: Поскольку параллельный сборщик не сжимает и не организует пространство памяти, он будет генерировать «фрагментацию» после работы в течение определенного периода времени, что снижает эффективность работы. Это значение определяет, сколько раз сжимать и упорядочивать пространство памяти после запуска GC.

-XX:+UseCMSCompactAtFullCollection:Включите сжатие для старого поколения. Может повлиять на производительность, но может устранить фрагментацию

3) Вспомогательная информация, связанная с

-XX:+PrintGC
-XX:+PrintGCDetails

-XX: + Формат вывода PrintGC:

[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs]

-XX:+PrintGCDetails Форма вывода:

[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs

9. Как распечатать информацию о стеке потоков.

Идеи:Вы можете поговорить о командах jps, top и jstack, а затем задать онлайн-вопросы, чтобы ответить на них.

мой ответ:

  • Введите jps, чтобы получить идентификатор процесса.
  • top -Hp pid Получить производительность процессорного времени всех потоков в этом процессе
  • Команда jstack pid для просмотра состояния стека текущего процесса Java.
  • Или jstack -l > /tmp/output.txt для печати информации о стеке в текстовый файл.
  • Вы можете использовать позиционирование стека fastthread,fastthread.io/

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

Идеи:Давайте сначала поговорим об определениях четырех видов ссылок.Вы можете говорить о них в сочетании с кодом или можете расширить использование слабых ссылок в ThreadLocalMap.

мой ответ:

1) Сильные ссылки

Обычно новый объект — это сильная ссылка, например Object obj = new Object(); Даже в случае нехватки памяти JVM скорее выдаст ошибку OutOfMemory, чем переработает такой объект.

2) Мягкие ссылки

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

SoftReference<String> softRef=new SoftReference<String>(str);     // 软引用

полезность:Мягкие ссылки имеют важные практические применения, например, кнопка «Назад» в браузере. Когда вы нажимаете назад, отображается ли содержимое веб-страницы при повторном запросе или извлечении из кэша? Это зависит от конкретной стратегии реализации.

(1) Если веб-страница повторно использует свое содержимое в конце просмотра, ее необходимо перестроить, когда вы нажимаете «Назад», чтобы просмотреть ранее просмотренную страницу.

(2) Если просматриваемые веб-страницы хранятся в памяти, это приведет к большому расходу памяти и даже к переполнению памяти.

Следующий код:

Browser prev = new Browser();               // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用        
if(sr.get()!=null){ 
    rev = (Browser) sr.get();           // 还没有被回收器回收,直接获取
}else{
    prev = new Browser();               // 由于内存吃紧,所以对软引用的对象回收了
    sr = new SoftReference(prev);       // 重新构建
}

3) Слабые ссылки

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

String str=new String("abc");    
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str=null;
等价于
str = null;
System.gc();

4) Фантомные ссылки

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

11. Будет обновлено

Ссылка и спасибо

Личный публичный аккаунт

Приглашаем всех обратить внимание, учиться и обсуждать вместе.