Интервью с Java — объяснение модели памяти JVM

Java

У людей часто возникает такое сомнение, а нужно ли понимать принципы JVM для Java-разработки? Я не знаю JVM, но я все еще могу развиваться. Действительно, но если вы понимаете JVM, вы можете пойти дальше по этому техническому пути.

Важность JVM

Прежде всего, вы должны знать, что для запуска приложения Java мы должны сначала установить JDK или JRE. Это связано с тем, что приложения Java компилируются в байт-код, а затем выполняются через байт-код в JVM, которая является основным компонентом JRE.

преимущество

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

недостаток

Хотя этот механизм повышает эффективность разработки Java, он также приводит к тому, что Java-разработчики слишком сильно полагаются на автоматизацию и ослабляют способность управлять памятью, так что система подвержена исключениям памяти кучи JVM, несоответствующей сборке мусора (GC) и GC. , Такие проблемы, как слишком частое время, будут напрямую влиять на производительность службы приложений.

модель памяти

Модель памяти JVM разделена на 5 областей:堆(Heap),方法区(Method Area),程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native Method Stack).

в,堆(Heap),方法区(Method Area)за线程共享,程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native Method Stack)за线程隔离.

куча

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

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

С обновлением версии Java произошли некоторые изменения в его содержании:

В версии Java6 постоянное поколение находится в области памяти, не относящейся к куче; в версии Java7 статические переменные и пулы констант времени выполнения постоянного поколения объединены в кучу; в Java8 постоянное поколение元空间(в локальной памяти) заменил.

зачем использовать元空间А как насчет замены постоянного поколения?

  1. Чтобы интегрировать HotSpot JVM и JRockit VM, поскольку JRockit не имеет постоянной генерации, нет необходимости настраивать постоянную генерацию.
  2. Памяти постоянного поколения часто бывает недостаточно или происходит переполнение памяти (должна быть самая большая часть памяти в JVM), что приводит к исключениюjava.lang.OutOfMemoryError: PermGen. В версии JDK1.7 указанный размер области PermGen составляет 8 М. Поскольку информация о метаданных классов в PermGen может собираться на каждом FullGC, скорость восстановления низкая, а результаты неудовлетворительны, а также сколько места выделено. для PermGen сложно определить, размер PermSize зависит от многих факторов, таких как общее количество классов, загружаемых JVM, размер константного пула и размер метода.

Увидев это, я, естественно, подумал об алгоритме рециркуляции GC. Не волнуйтесь, я объясню его в следующей статье. Сейчас он по-прежнему в основном основан на модели памяти JVM.

Область метода

Что такое область метода?

Область методов в основном используется для хранения информации, относящейся к классу, которая была загружена виртуальной машиной, в том числе类信息,常量池(пулы строковых констант и все примитивные типы имеют соответствующие пулы констант),运行时常量池. Среди них информация о классе также включает такую ​​информацию, как версия, поля, методы, интерфейсы и родительские классы класса.

информация о классе

Когда JVM выполняет класс, он должен быть загружен, подключен и инициализирован.连接Он также включает три этапа проверки, подготовки и анализа.

При загрузке класса JVM сначала загрузит файл класса, а в файле класса есть информация описания, такая как версия, поле, метод и интерфейс класса, который类信息.

постоянный пул

в файле класса, кроме类信息, а другая часть информации — постоянный пул (Constant Pool Table), который используется для хранения различных字面量и符号引用.

Тот字面量и符号引用Что это?

Литералы включают строки (String a=«b»), константы базовых типов (final-modified переменные), а символические ссылки включают полные имена классов и методов (например, класс String, полное имя которого — Java/ lang/String), имена и дескрипторы полей, а также имена и дескрипторы методов.

постоянный пул времени выполнения

Когда класс загружается в память, JVM常量池хранить содержимое в运行时常量池; на этапе синтаксического анализа JVM заменяет символические ссылки прямыми ссылками (значение индекса объекта).

Например:

Когда строковая константа в классе находится в файле класса, она сохраняется в пуле констант файла класса.

После того, как JVM загрузит класс, JVM字符串常量ставить运行时常量池, а на этапе синтаксического анализа укажите значение индекса строкового объекта.

运行时常量池Он является глобально общим, и несколько классов совместно используют пул констант времени выполнения, поэтому несколько идентичных строк в пуле констант в файле класса будут существовать только в пуле констант времени выполнения.

Говоря об этом, у вас немного закружилась голова? Честно говоря, я был в тумане, когда увидел это содержимое. Вот пример, который поможет вам понять:

    public static void main(String[] args) {
        String str = "Hello";
        System.out.println((str == ("Hel" + "lo")));

        String loStr = "lo";
        System.out.println((str == ("Hel" + loStr)));

        System.out.println(str == ("Hel" + loStr).intern());
    }

Результатом его работы является:

true
false
true

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

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

Последнее верно, потому что метод intern() класса String проверит, есть ли равная строка в пуле констант (результат вызова метода equals() равен), если да, то вернет ссылку на string, если нет, добавьте свою строку в пул констант.

Произошла ошибка

  1. OutOfMemoryErrorПоявляется, когда область метода не может удовлетворить требования к выделению памяти, например постоянное добавление данных в пул констант,运行时常量池будет переполнен, и будет сообщено об ошибке.

Регистр счетчика программ

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

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

Видно, что счетчик программ связан с переключением контекста.

Стек виртуальных машин (стек виртуальных машин)

Стек виртуальной машины — это пространство памяти для отдельных потоков, созданное с помощью потоков Java.

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

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

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

Произошла ошибка

  1. StackOverflowErrorКогда для стековой памяти установлено фиксированное значение, эта ошибка возникает, когда стековая память, необходимая для выполнения программы, превышает установленное фиксированное значение.
  2. OutOfMemoryErrorПроисходит, когда память стека настроена на динамический рост, и эта ошибка возникает, когда JVM пытается запросить больше памяти, чем доступно.

Стек собственных методов

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

Но нативные методы реализованы не в Java, а в C.

То есть в локальном стеке методов, который состоит изnativeМодификация, реализованная на языке Си.

Суммировать

Вышеизложенное является основным введением модели памяти JVM.У меня есть общее представление о 5 разделах и их соответствующих значениях и функциях.Отсюда мы можем продолжить расширять модель памяти Java, алгоритм GC и т. д., что я буду объяснить в следующих статьях. Если у вас есть какие-либо идеи, пожалуйста, оставьте сообщение ниже.

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

death00.github.io/