Обмен технологиями

Вопрос для собеседования 005-Java-JVM (Часть 1)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Вопрос для собеседования 005-Java-JVM (Часть 1)

Вопросы для самопроверки

  • 1. Из каких частей состоит JVM?
  • 2. Какие области входят в область данных времени выполнения?
  • 3. Какие данные хранятся в стеке и куче соответственно?
  • 4. Почему нам следует заменить постоянное поколение (PermGen) метапространством (MetaSpace)?
  • 5. Понимаете ли вы основную структуру кучи? При каких обстоятельствах объект перейдет в старое поколение?
  • 6. В какой области памяти размещаются крупные предметы?
  • 7. Каков процесс создания объектов Java?

Вопрос ответ

1. Из каких частей состоит JVM?

Ответ: JVM — это исполняемый файл.байт-код (.class) файловый виртуальный компьютер, который также обеспечивает управление памятью, сборку мусора и другие механизмы. Он содержит следующие основные части.

  • Подсистема загрузки классов: отвечает за загрузку файлов байт-кода (.class) в JVM.
  • Область данных времени выполнения: это область памяти, используемая JVM во время выполнения.
  • Механизм выполнения: отвечает за интерпретацию или компиляцию байт-кода в машинный код для выполнения процессором.
  • Интерфейс собственной библиотеки: предоставляет набор API для вызова собственных библиотек, написанных в операционной системе или на других языках.

2. Какие области входят в область данных времени выполнения?

Ответ: Область данных времени выполнения — это область памяти, выделяемая JVM при выполнении программы Java.

  • Счетчик программ: это небольшая область памяти и адрес инструкции байт-кода, выполняемой потоком в данный момент. Если поток выполняет собственный метод, значение этого счетчика не определено.
  • Стек виртуальной машины Java: каждый поток при создании создает стек виртуальной машины, который используется для хранения таблицы локальных переменных потока, кадра операнда, динамической ссылки, информации о выходе метода и т. д. Стек виртуальной машины Java содержит несколько кадров стека. Процесс от каждого вызываемого метода до завершения выполнения соответствует процессу помещения кадра стека в стек виртуальной машины.
  • Стек собственных методов: это пространство, подготовленное JVM для запуска собственных методов. Он имеет функции, аналогичные стеку виртуальной машины Java. Это модель памяти, которая описывает процесс выполнения собственных методов.
  • Куча: используется для хранения почти всех экземпляров объектов и массивов и является основной областью, в которой работает сборщик мусора.
  • Область метода: используется для хранения информации о классе, констант, статических переменных, кода, скомпилированного JIT-компилятором, и т. д., загружаемых JVM. До JDK1.8 он был реализован как постоянное поколение. Начиная с JDK1.8, постоянное поколение заменяется исходным пространством. Metaspace использует локальную память, а не динамическую память.
    Область данных времени выполнения виртуальной машины Java

3. Какие данные хранятся в стеке и куче соответственно?

Ответ: Данные хранятся в стеке (стеке виртуальной машины Java):

  • Таблица локальных переменных: в основном используется для хранения параметров метода и локальных переменных внутри метода. Типы данных включают базовые типы данных и ссылки на объекты.
  • Стек операндов: используется для временного хранения инструкций операции и промежуточных результатов во время выполнения метода.
  • Динамическая ссылка: ссылка на пул констант класса, к которому принадлежит метод, используемая для разрешения ссылок на символы в методе.
  • Адрес возврата метода: хранит адрес следующей инструкции, выполняемой после вызова метода.
    Данные, хранящиеся в куче:
  • Экземпляр объекта: Экземпляр объекта, созданный с помощью нового ключевого слова в программе, включая свойства и методы объекта.
  • Массив: все типы массивов, включая массивы базовых типов и массивы объектов.

4. Почему нам следует заменить постоянное поколение (PermGen) метапространством (MetaSpace)?

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

  • Повысьте гибкость и эффективность управления памятью. Размер памяти постоянной генерации устанавливается при запуске JVM и не может регулироваться динамически. Metaspace использует локальную память вместо кучи Java, и ее размер можно динамически регулировать по мере необходимости.
  • Решите проблему выгрузки классов и сборки мусора: поведение GC постоянной генерации сложное и непредсказуемое, а эффективность переработки низкая.
  • Обеспечьте лучшую производительность и стабильность. Использование метапространства делает управление памятью JVM более унифицированным и последовательным, поскольку метапространство, как и другие области памяти, управляется с использованием локальной памяти. Это упрощает стратегии управления памятью и повышает общую производительность и стабильность.
  • Упрощение управления памятью JVM

5. Понимаете ли вы основную структуру кучи? При каких обстоятельствах объект перейдет в старое поколение?

Ответ: Базовая структура кучи в основном состоит из нового поколения, старого поколения и постоянного поколения. После JDK8 постоянное поколение заменяется метапространством и использует для хранения локальную память.

  • Кайнозойское поколение: развитие нового поколения подразделяется на область Эдема и две области выживания (Выживший 0 и Выживший 1).
    • Область Эдема: вновь созданные объекты сначала выделяют память в области Эдема.
    • Область выживания (S0, S1): используется для хранения объектов, переживших сборку мусора нового поколения. После каждого второстепенного GC уцелевшие объекты будут копироваться туда и обратно между этими двумя областями.
  • Старое поколение: объекты, которые все еще живы после нескольких второстепенных сборок мусора. Сбор мусора (Major GC или Full GC) в старом поколении выполняется реже.
  • Постоянное поколение/метапространство: используется для хранения метаданных классов, включая определения классов, константы, статические переменные, скомпилированный код «точно в срок» и т. д.

Ситуация, когда объект находится в старом поколении:

  • Достигнут порог возраста: у каждого объекта есть возраст, когда память выделяется в новом поколении, и этот возраст будет увеличиваться на 1 после каждого второстепенного GC. Когда возраст достигнет определенного порога (по умолчанию — 15), объект будет переведен в старое поколение.
  • Большой объект: если объект слишком велик и превышает порог, установленный JVM, объект будет напрямую выделять пространство в старом поколении.
  • Недостаточно места в зоне выживших: если в зоне выживших недостаточно места для размещения всех выживших объектов во время Minor GC, эти объекты будут
  • Динамическое определение возраста объекта: Если размер всех объектов одного возраста в пространстве Выжившего превышает половину пространства Выжившего, то объекты, возраст которых больше или равен этому возрасту, могут напрямую перейти в старое поколение.
// 动态年龄计算代码
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
 //survivor_capacity是survivor空间的大小
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);//TargetSurvivorRatio 为50
size_t total = 0;
uint age = 1;
while (age < table_size) {
total += sizes[age];//sizes数组是每个年龄段对象大小
if (total > desired_survivor_size) break;
age++;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
  ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6. В какой области памяти размещаются крупные предметы?

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

# 将大于1MB的对象直接分配在老年代
java -XX:PretenureSizeThreshold=1m -jar your-application.jar
  • 1
  • 2

7. Каков процесс создания объектов Java?

отвечать:

  1. Проверка загрузки классов
    • Если класс не был загружен, подключен и инициализирован, JVM сначала загрузит класс. Это включает в себя следующие шаги:
      • Загрузка: прочитайте файл класса через загрузчик классов и загрузите байт-код класса в память.
      • Подключение: включает в себя три этапа: проверка, подготовка и разбор. Проверьте правильность файлов классов, подготовьте статические переменные класса и выделите память, а также преобразуйте ссылки на символы в прямые ссылки.
      • Инициализация: выполнить блок статической инициализации класса и инициализацию статических переменных.
  2. выделение памяти
    • JVM выделяет память для новых объектов в куче. Размер выделяемой памяти определяется структурой объекта, включая заголовок объекта и данные экземпляра.
    • JVM имеет два основных способа распределения памяти:
      • Удар по указателю: если память в куче является регулярной, указатель выделения должен переместиться только на указанное расстояние в область свободной памяти.
      • Список свободных ресурсов. Если память в куче нерегулярна, JVM необходимо поддерживать список свободных мест и находить соответствующий блок из списка свободных при выделении памяти.
  3. инициализировать нулевым значением
    • JVM инициализирует все переменные экземпляра объекта значениями по умолчанию. Например, переменные числового типа будут инициализированы значением 0, переменные логического типа — значением false, а переменные ссылочного типа — значением null.
  4. Установить заголовок объекта
    • Установите информацию заголовка объекта в пространстве памяти объекта, которая включает в себя хеш-код объекта, возраст создания GC, флаг состояния блокировки, блокировку, удерживаемую потоком, смещенный идентификатор потока и т. д.
  5. Инициализация конструктора
    • Вызовите конструктор объекта, чтобы завершить инициализацию объекта. Сюда входит выполнение явных операций инициализации переменных экземпляра, а также кода в теле конструктора. Конкретные шаги заключаются в следующем:
      • Выполните блок инициализации экземпляра класса.
      • Выполните метод конструктора родительского класса сверху вниз в соответствии с иерархией наследования.
      • Инициализируйте переменные экземпляра явно указанными значениями.
      • Выполните основную часть метода конструктора класса.
/**
 * 创建对象的示例代码
 */
public class MyClass {
    private int value;

    public MyClass(int value) {
        this.value = value;
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass(10);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • Процесс выполнения приведенного выше примера кода выглядит следующим образом:
    • Загрузка классов: JVM проверяет, загружен ли MyClass. Если он не загружен, загружается класс MyClass.
    • Распределение памяти: выделите память в куче для нового экземпляра MyClass.
    • Инициализация памяти: инициализация выделенной памяти значениями по умолчанию.
    • Установить заголовок объекта: установить метаданные в заголовке объекта.
    • Инициализация конструктора: выполните конструктор MyClass и инициализируйте значение переменной экземпляра равным 10.

Рекомендации