10 классических и легко упускаемых из виду вопросов на собеседовании с JVM

интервью Java

предисловие

Я собрал 10 классических и легко упускаемых из виду вопросов интервью JVM, спасибо за внимание, всем привет

адрес github, спасибо за каждую звезду

GitHub.com/Я бы хотел 123/Java…

публика:маленький мальчик собирает улиток

1. Должен ли объект размещаться в куче? Вы узнали о методах анализа побега?

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

  • Что такое анализ побега?

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

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

  • Пример анализа побега
/**
 *  @author 捡田螺的小男孩
 */
public class EscapeAnalysisTest {

    public static Object object;

    //StringBuilder可能被其他方法改变,逃逸到了方法外部。
    public StringBuilder  escape(String a, String b) {
        //公众号:捡田螺的小男孩
        StringBuilder str = new StringBuilder();
        str.append(a);
        str.append(b);
        return str;
    }

    //不直接返回StringBuffer,不发生逃逸
    public String notEscape(String a, String b) {
        //公众号:捡田螺的小男孩
        StringBuilder str = new StringBuilder();
        str.append(a);
        str.append(b);
        return str.toString();
    }

    //外部线程可见object,发生逃逸
    public void objectEscape(){
        object = new Object();
    }

    //仅方法内部可见,不发生逃逸
    public void objectNotEscape(){
        Object object = new Object();
    }
}

Преимущества анализа побега

  • Размещение в стеке может снизить частоту работы сборщика мусора.
  • Устранение синхронизации, если объект оказывается доступным только из одного потока, то операции над этим объектом могут не требовать синхронизации.
  • Скалярная замена разлагает объекты на базовые типы, а выделение памяти теперь происходит не в куче, а в стеке. Преимущества этого заключаются, во-первых, в уменьшении использования памяти, поскольку нет необходимости генерировать заголовки объектов. Во-вторых, эффективность восстановления памяти программ высока, а частота GC также будет снижена.

2. Почему виртуальная машина использует метапространство вместо постоянного поколения?

Что такое метапространство? Что такое постоянное поколение? Зачем использовать метапространство вместо постоянной генерации?Давайте рассмотримобласть методаИтак, посмотрите на карту памяти данных времени выполнения виртуальной машины, как показано ниже:

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

Что такое постоянное поколение? Какое отношение это имеет к области методов?

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

Что такое метапространство? Какое отношение это имеет к области методов?

Для Java8 HotSpots отменили постоянное поколение и заменили его на Metaspace. Другими словами, область метода осталась прежней, но реализация изменилась: от постоянной генерации к метапространству.

Почему постоянное поколение было заменено метапространством?

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

постоянное поколениеРазмер настраивается следующими двумя параметрами~

  • -XX:PremSize: установить начальный размер постоянного поколения
  • -XX:MaxPermSize: Установить максимальное значение постоянного поколения, по умолчанию 64M

запостоянное поколение, если динамически генерируется много классов, то, скорее всего, появитсяjava.lang.OutOfMemoryError: ошибка пространства PermGen, потому что конфигурация пространства постоянной генерации ограничена. Наиболее типичный сценарий — это когда в веб-разработке много jsp-страниц.

  • После JDK8 область метода существует в метапространстве (Metaspace). Физическая память больше не граничит с кучей, а находится непосредственно в локальной памяти, теоретически машинаНасколько велика память, насколько велик метапространство.

Размер метапространства можно задать следующими параметрами:

  • -XX:MetaspaceSize, начальный размер пространства, достижение этого значения вызовет сборку мусора для выгрузки типа, а сборщик мусора скорректирует значение: если освобождается большой объем пространства, уменьшите значение соответствующим образом; если небольшой объем пространства release , затем соответствующим образом увеличьте значение, если оно не превышает MaxMetaspaceSize.
  • -XX:MaxMetaspaceSize, максимальное пространство, по умолчанию не ограничено.
  • -XX:MinMetaspaceFreeRatio, после GC, процент от минимальной оставшейся емкости метапространства, уменьшающий сборку мусора, вызванную выделенным пространством.
  • -XX:MaxMetaspaceFreeRatio, после GC, процент от максимальной оставшейся емкости метапространства, уменьшающий сборку мусора, вызванную освобождением места

Итак, зачем использовать метапространство для замены постоянного поколения?

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

3. Что такое Stop The World и OopMap? Что такое безопасная точка?

В процессе сборки мусора участвуют движущиеся объекты. Чтобы обеспечить правильность обновления ссылок на объекты, все пользовательские потоки должны быть приостановлены.Такая приостановка описывается разработчиком виртуальной машины какStop The World.

В HotSpot существует структура данных (таблица сопоставления), называемаяOopMap. Как только действие по загрузке класса будет завершено, HotSpot рассчитает, какой тип данных находится по какому смещению в объекте, и запишет его в OopMap. При своевременной компиляцииконкретное местоСгенерируйте OopMap для записи того, какие места в стеке и в регистрах являются ссылками.

Эти конкретные места в основном находятся в:

  • 1. Конец петли (несчетная петля)
  • 2. Перед возвратом метода / после вызова инструкции вызова метода
  • 3. Место, где может быть выдано исключение

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

4. Расскажите об основных компонентах JVM и их роли?

JVM содержит две подсистемы и два компонента, а именно

  • Загрузчик классов (подсистема загрузки классов)
  • Исполнительный механизм (подсистема исполнительного механизма);
  • Область данных времени выполнения (компонент области данных времени выполнения)
  • Native Interface (локальные компоненты интерфейса).
  • Загрузчик классов (загрузка классов):Загрузите файл класса в область методов области данных среды выполнения в соответствии с заданным полным именем класса (например, java.lang.Object).
  • Двигатель исполнения: Выполнить инструкцию класса.
  • Родной интерфейс:Взаимодействие с нативной библиотекой — это интерфейс для взаимодействия с другими языками программирования.
  • Область данных времени выполнения: То есть память JVM, о чем мы часто говорим.

Сначала исходный код Java преобразуется компилятором в байт-код, а затем загрузчик классов (загрузка классов) загружает байт-код в память и помещает его в область методов области данных времени выполнения, а файл байт-кода — это только JVM. Набор спецификаций набора команд не может быть напрямую передан в базовую операционную систему для выполнения. Поэтому для преобразования байт-кода в базовые системные инструкции требуется специальный механизм выполнения синтаксического анализатора команд (Execution Engine), а затем передача его на ЦП для выполнения.В этом процессе необходимо вызвать собственный интерфейс библиотеки (Native Interface) других языков, чтобы реализовать функцию всей программы.

5. Что такое поток демона? В чем разница между потоком демона и потоком, не являющимся демоном? Какова роль потока демона?

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

В чем разница между потоком демона и потоком, не являющимся демоном?Давайте посмотрим на это на примере ~

    /**
      * 关注公众号:捡田螺的小男孩
      */
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()-> {
                while (true) {
                    try {
                        Thread.sleep(1000);
                        System.out.println("我是子线程(用户线程.I am running");
                    } catch (Exception e) {
                    }
                }
        });
        //标记为守护线程
        t1.setDaemon(true);
        //启动线程
        t1.start();

        Thread.sleep(3000);
        System.out.println("主线程执行完毕...");
    }

результат операции:

Можно обнаружить, что после пометки как потока демонаОсновной поток уничтожается и останавливается, а поток демона уничтожается вместе с ним.. Давайте посмотрим на эффект удаления флага опекуна t1.setDaemon(true):

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()-> {
                while (true) {
                    try {
                        Thread.sleep(1000);
                        System.out.println("我是子线程(用户线程.I am running");
                    } catch (Exception e) {
                    }
                }
        });
        //启动线程
        t1.start();

        Thread.sleep(3000);
        System.out.println("主线程执行完毕...");
    }

Следовательно, когда основной поток завершается, JVM также завершает работу, и в то же время будет перезапущен поток демона, даже если это бесконечный цикл. Если это пользовательский поток, он будет продолжать работать в бесконечном цикле. ЭтоРазница между потоками демона и потоками, не являющимися демонамиЛа.

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

6. Вы поняли WeakHashMap? Как это работает?

WeakHashMapПодобно HashMap, разница в том, что ключ WeakHashMapслабая ссылкаключ.

говоря ослабая ссылка, просмотрите четыре ссылки здесь

  • Сильная ссылка: Object obj=new Object(), пока существует связь строгой ссылки, сборщик мусора никогда не вернет объект, на который указывает ссылка.
  • Мягкая ссылка: Как правило, она не будет перезагружена.Если памяти недостаточно, она будет переработана при переполнении.
  • Слабые ссылки: когда сборщик мусора начинает работать, он будет собирать объекты, связанные только со слабыми ссылками, независимо от того, достаточно ли текущей памяти.
  • Фантомные ссылки: единственная цель установки фантомной ссылки на объект — получение системного уведомления, когда объект истребуется.

Именно потому, что WeakHashMap использует слабые ссылки,его объекты могут быть переработаны в любое время. Раздел поведения класса WeakHashMapЗависит от действий сборщика мусора, Дважды вызовите метод size(), чтобы вернуть разные значения, дважды вызовите метод isEmpty(), один раз, чтобы вернуть значение true, и один раз, чтобы вернуть значение false.возможный.

WeakHashMapПринцип работыОтветьте на эти два пункта:

    1. WeakHashMap обладает характеристиками слабой ссылки: объекты перерабатываются в любое время.
    1. Как WeakHashMap удаляет запись при сборке мусора?

Entry внутри WeakHashMap наследует WeakReference, то есть слабую ссылку, поэтому она имеет характеристики слабой ссылки.может быть переработан в любое время. Посмотрите на исходный код:

    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
        V value;
        final int hash;
        Entry<K,V> next;

        /**
         * Creates new entry.
         */
        Entry(Object key, V value,
              ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }
        ......

Как WeakHashMap удаляет Entry?После того, как сборщик мусора каждый раз очищает объект, эталонный объект помещается в ReferenceQueue, а затем проходит через очередь, чтобы удалить его. Операция добавления, удаления, изменения и проверки WeakHashMap заключается в прямом/косвенном вызове метода expungeStaleEntries() для своевременной очистки записей с истекшим сроком действия. Вы можете посмотреть исходный код expungeStaleEntries:

  /**
     * Expunges stale entries from the table.
     */
    private void expungeStaleEntries() {
        for (Object x; (x = queue.poll()) != null; ) {
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                while (p != null) {
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            table[i] = next;
                        else
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

7. Знаете ли вы сахар синтаксиса Java? Расскажите мне о 12 синтаксических сахарах, обычно используемых в Java?

Синтаксический сахар, также известный как «подслащенный синтаксис», делает программы более краткими и читабельными. Наиболее часто используемые синтаксические сахара в Java в основном включают 12 типов, таких как дженерики, параметры переменной длины, условная компиляция, автоматическая распаковка и внутренние классы.

  • Синтаксический сахар 1. переключатель поддерживает String и перечисление
  • Синтаксический сахар 2, дженерики
  • Синтаксический сахар три, автоматическая упаковка и распаковка
  • Синтаксический сахар четыре, параметры переменной длины метода
  • Синтаксис сахара пять, перечисление
  • Синтаксический сахар шесть, внутренний класс
  • Синтаксический сахар семь, условная компиляция
  • Синтаксический сахар восемь, утверждение
  • Синтаксический сахар девять, числовые литералы
  • Синтаксический сахар десять, для каждого
  • Синтаксический сахар одиннадцать, попытка с ресурсом
  • Синтаксический сахар 12. Лямбда-выражения

Заинтересованные друзья, вы можете прочитать эту статью:Если вы не понимаете эти 12 синтаксических сахаров, не говорите, что знаете Java!

8. Что такое столкновение указателей? Что такое бесплатный список? Что такое ТЛАБ?

В обычных условиях объекты JVM помещаются в динамическую память (за исключением анализа побега). Когда проверка загрузки класса проходит успешно, виртуальная машина Java начинает выделять память для нового объекта. Если память в Java-куче абсолютно регулярна, то вся используемая память помещается в одну сторону, свободная память — в другую, а посередине ставится указатель как индикатор демаркационной точки, а выделенная память - это только то, что указатель перемещает экземпляр, равный размеру объекта, в направлении свободного места. Этот метод выделения "столкновение указателя".

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

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

Действие по выделению памяти может быть разделено на разные области в соответствии с потоком, и каждый поток предварительно выделяет небольшой участок памяти в куче Java, которыйTLAB (Thread Local Allocation Buffer, локальный буфер распределения потоков). Виртуальная машина устанавливает его с помощью -XX:UseTLAB.

9. Рабочий процесс сборщика мусора CMS, отличие сборщика CMS от сборщика G1.

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

Разница между CMS Collector и G1 Collector:

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

10. Настройка JVM

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

память стека

  • -Xms устанавливает начальный размер кучи
  • -Xmx устанавливает максимальный размер кучи
  • -Xmn устанавливает размер молодого поколения, что эквивалентно одновременной настройке -XX:NewSize и -XX:MaxNewSize на одно и то же значение.
  • -Xss размер стека на поток
  • -XX:NewSize установить размер молодого поколения (для 1.3/1.4)
  • -XX:MaxNewSize максимальное значение молодого поколения (для 1.3/1.4)
  • -XX:NewRatio отношение молодого поколения к старому (исключая постоянное поколение)
  • -XX: SurvivorRatio Отношение площади Эдема к площади выживших.
  • -XX:PretenureSizeThreshold Когда созданный объект превышает указанный размер, непосредственно выделять объект в старом возрасте.
  • -XX:MaxTenuringThreshold Устанавливает порог максимального возраста для объектов, реплицируемых в Survivor, и если порог превышает порог, то он будет переведен в старость

Связанный со сборщиком мусора

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

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

  • -XX:+PrintGCDetails Печать сведений о сборщике мусора
  • -XX:+HeapDumpOnOutOfMemoryError позволяет JVM автоматически создавать моментальный снимок памяти при переполнении памяти для устранения неполадок.
  • -XX:+DisableExplicitGC отключает системный System.gc(), чтобы предотвратить проблемы, вызванные ручным запуском FGC по ошибке.
  • -XX:+PrintTLAB Просмотр использования пространства TLAB

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

публика

Публичный аккаунт стека серверных технологий: маленький мальчик собирает улиток