Модель памяти JVM (JMM) и область памяти, больше не путайте

JVM

предисловие

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

Модель памяти JVM (JMM)

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

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

Связь: в императивном программировании есть два способа связи между потоками.

  • Общая память (модель разделяемой памяти: общее состояние программы распределяется между потоками, и потоки записываются для чтения общего состояния в памяти дляСкрытыйобщаться)
  • Передача сообщений (модель передачи сообщений: между потоками нет общедоступного состояния, и потоки должны явно отправлять сообщения для связиявныйобщаться)

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

  • В модели параллелизма с общей памятью синхронизация выполняется явно, и программист должен явно указать, что метод или часть кода должны быть разделены между потоками.взаимоисключающийвоплощать в жизнь
    • Типичный метод связи с общей памятью — это связь через общие объекты.
  • В параллельной модели передачи сообщений синхронизация является неявной, поскольку отправка сообщения должна предшествовать получению сообщения.
    • Типичными методами передачи сообщений в Java являются wait() и notify().

Обобщить:

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

Абстрактная структура модели памяти Java

  • С абстрактной точки зрения JMM определяет абстрактную связь между потоками и основной памятью:
    • Общие переменные между потоками хранятся в основной памяти, и каждый поток имеет частную локальную память (локальную память), в которой хранится копия потока для чтения/записи общих переменных.
    • Локальная память является абстракцией JMM и на самом деле не существует. Он охватывает кеши, буферы записи, регистры и другие оптимизации оборудования и компилятора.
  • Связь между потоками Java регулируется моделью памяти Java (JMM), которая определяет, когда запись потока в общую переменную видна другому потоку.
    • JMM предоставляет Java-программистам гарантии видимости памяти, контролируя взаимодействие между основной памятью и локальной памятью каждого потока.
  • В Java все поля экземпляра, статические поля и элементы массива хранятся в куче памяти, которая совместно используется потоками. Локальные переменные, формальный параметр метода и параметр обработчика исключений больше не являются общими для потоков, они не имеют проблем с видимостью памяти и не зависят от модели памяти.

Спецификации, относящиеся к модели памяти Java:JSR 133: JavaTM Memory Model and Thread Specification Revision

Область памяти Java (область данных времени выполнения)

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

До версии JDK 1.8, если вы не знаете разницу между областью данных времени выполнения, определенной спецификацией JVM, и соответствующей реализацией JVM HotSpot, это не было большой проблемой.Конечно, большинство блогов делают то же самое. Но после появления MetaSpace необходимо выяснить разницу между ними, иначе трудно понять различие между областью метода, постоянной зоной и метапространством.

Область данных времени выполнения, определенная спецификацией JVM

Ссылаться на:Документ спецификации JVM для JDK8

Я перевел версию для области данных времени выполнения документа, в которой подробно представлена ​​каждая область данных времени выполнения:Спецификация виртуальной машины Java, версия Java SE 8 — область данных времени выполнения (перевод)

Спецификация определяет 6 областей данных времени выполнения: регистр ПК (счетчик программ), стеки виртуальной машины Java (стек виртуальной машины Java), куча (куча), область метода (область методов), измерение пула констант времени выполнения (пул констант времени выполнения). пул), Native Method Stacks (нативный стек методов).

  • В оригинале также сказаноEach run-time constant pool is allocated from the Java Virtual Machine's method area.Пул констант времени выполнения размещается в области методов JVM.

Итак, вот картина, которую мы часто видим:

  • Стоит отметить, что все эти области данных времени выполнения, определенные в спецификации,АннотацияКонцепция не ограничивает конкретную реализацию. Следовательно, эти области данных времени выполнения, реализованные конкретной виртуальной машиной, не обязательно изолированы друг от друга. Например:Кадр стека может быть выделен в куче(например: CLDC HI).

Область данных времени выполнения в конкретной виртуальной машине Java (в качестве примера возьмем HotSpot VM)

Введение в HotSpot VM

HotSpot VM — это виртуальная машина в Sun JDK и OpenJDK, и в настоящее время она является наиболее широко используемой виртуальной машиной Java.

На конференции JavaOne в 2006 году Sun объявила, что в конечном итоге откроет исходный код Java, и в следующем году последовательно выпустила исходный код различных частей JDK (включая, конечно же, HotSpot VM) в соответствии с соглашением GPL. И строить OpenJDK на этой основе. Таким образом, HotSpot VM стала общей виртуальной машиной для двух проектов JDK, чрезвычайно близких по реализации к Sun JDK и OpenJDK.

В 2008 и 2009 годах корпорация Oracle приобрела соответственно BEA Corporation и Sun Corporation, так что у Oracle одновременно есть две превосходные виртуальные машины Java: JRockit VM и HotSpot VM. Oracle объявила, что в ближайшем будущем завершит интеграцию двух виртуальных машин, сделав их взаимодополняющими. (Это также одна из предысторий большого пересмотра области данных среды выполнения HotSpot VM в JDK 1.8)

Структура виртуальной машины HotSpot

HotSpot VM объединяет стек виртуальной машины и собственный стек методов в один:

В версиях до JDK 1.8 реализация области метода на диаграмме в HotSpot VMPermGen(постоянная генерация), которого нет на других JVM. Во времена JDK 1.8 виртуальная машина HotSpot заменила реализацию области метода наMeatspace(метапространство). Таким образом, по сути, и постоянное поколение, и метапространство являются реализациями областей методов, но детали их реализации различаются.

  • Трудно определить размер информации о классе и методе, поэтому трудно указать размер постоянной генерации.Если он слишком мал, то легко переполнить постоянную генерацию, а если слишком велик, то легко вызвать переполнение старого поколения.
  • Удаление постоянного поколения — это попытка интегрировать JVM HotSpot и виртуальную машину JRockit, поскольку JRockit не имеет постоянного поколения и не нуждается в настройке постоянного поколения.
  • Работа по удалению постоянного поколения началась в JDK 1.7. В JDK1.7 часть данных, хранящихся в постоянном поколении, была перенесена вJava HeapилиNative Heap. Например, ссылки на символы (Символы) переносятся вnative heap; литералы (интернированные строки) перемещены вjava heap;статика класса перемещена вjava heap.

Некоторые различия между постоянной генерацией и метапространством

Определено в спецификации JVM:Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it.Область методов логически является частью кучи. (Область метода виртуальной машины HotSpot до JDK1.7 также физически была частью кучи)

  • Постоянная генерация выделяется в куче (внутри JVM), метапространство использует прямую память (вне JVM)
  • Переполнение постоянного поколения:java.lang.OutOfMemoryError: PermGen space, метапространство переполняется:java.lang.OutOfMemoryError: Metaspace
  • GC постоянного поколения и GC старого поколения связаны вместе, когда один из них заполнится, будет запущен GC двух областей, жизненный цикл класса и его метаданных в метапространстве такой же, как у соответствующего Если он снова выживет, GC вернет все соответствующее пространство (каждый загрузчик классов имеет отдельное пространство для хранения), и нет необходимости сканировать и сжимать трудоемкую операцию.