«Пять минут в день поиграйте с JVM»: структура объектной памяти

Java

Обзор

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

image-20190823221858767

заголовок объекта

Заголовок объекта разделен на две части, первая часть называется **"Mark Word", вторая часть используется для получения типа объектаУказатель типа**, если это объект массива, он также включает данные, записывающие длину массива.

В разных операционных системах память, занимаемая этими областями, также отличается, в 32-битной системе MarkWord занимает 32 бита пространства (то есть 4 байта). Указатель типа и данные длины массива совместно занимают 32-битное пространство.

В 64-разрядной операционной системе MarkWord занимает 64 бита пространства, а указатель типа составляет 64 бита (8 байтов) без включения сжатия указателя (CompressedOOPs), но только 32 бита (4 байта), когда включено сжатие указателя.

image-20190823225703812

Mark Word

Эта часть хранитданные времени выполнения самого объекта, структура данных этого фрагмента контента не фиксирована, он будет повторно использовать собственное пространство для хранения в соответствии с состоянием объекта,

image-20190823230559543

Вот фрагмент из файла markOop.hpp, который представляет следующие пять состояний объекта:

бит флага Флаг блокировки смещения условие
01 0 нет замка
01 1 Блокировка смещения
00 никто Легкий замок
10 никто тяжелый замок
11 никто GC Mark

Давайте посмотрим на структуру MarkWord дальше:

image-20190823231212050

Здесь мы видим, что структура состояний lock-free иbiasedlock определяется только во время инициализации (верхняя часть — это структура без сжатия COOPs-указателя, а нижняя часть — структура с включенным сжатием указателя),

Когда он находится в легковесной или тяжеловесной блокировке, записанный указатель объекта, согласно описанию JVM, считает, что в это время указатель по-прежнему 64-битный, а младшие два бита считаются равными 0; когда он находится в смещенная блокировка, запись для получения смещенной блокировки Указатель потока, который также является 64-битным;

image-20190823231522289

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

указатель типа

Иногда это используется, чтобы определить, принадлежит ли объекткакой экземпляр класса, а когда это нецелесообразно, это должно быть сделано в соответствии с выбором различных виртуальных машин для алгоритма реализации позиционирования объекта (например, JVM HotSpot использует этот тип указателя для получения данных типа объекта)

данные экземпляра

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

Правила хранения в этой части следуют порядку определения параметров и полей стратегии выделения виртуальных машин в исходном коде Java. pointer, Ordinary Object Pointers) тоже можно понимать как ссылку, о сжатии указателя мы поговорим в следующем разделе.

Здесь следует отметить, что переменные, определенные в родительском классе, появятся перед подклассом, но мы можем вставить меньшие переменные в подклассе в промежутки между большими переменными в родительском классе, установив для параметра CompactFileds значение true.

image-20190824120847519

Выровнять отступы

Эта часть содержимого не обязательно должна существовать, поскольку JVM Hot Spot указываетРазмер объекта должен быть целым числом, кратным 8 байтам., в C/C++ аналогичная функция называетсявыравнивание памяти, пространство памяти разделено по байтам.Теоретически кажется, что доступ к любому типу переменной может начинаться с любого адреса, но реальная ситуация такова, что при обращении к определенному типу переменной, к ней часто обращаются по определенному адреса памяти, для чего требуются различные типы данных, которые располагаются в пространстве по определенным правилам, а не последовательно друг за другом, что является выравниванием.

Выравнивание памяти следует двум правилам:

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

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

Нетрудно понять, почему в JVM оговаривается, что размер объекта должен быть целым числом, кратным 8 байтам, ведь в 64-битной системе (без включения сжатия указателей) в объекте много типов данных, занимающих 8 байт. Но в то же время есть и некоторые 4-байтные типы данных, в это время наш Padding играет роль в дополнении той части, которая меньше 8 байт и составляет целое число, кратное 8.

image-20190824121114907

публика