ПредыдущийКратко представлено в статьеsynchronized
путь ключевого слова, где блок синхронизированного кода используетmonitorenter
а такжеmonitorexit
Реализовано две инструкции, используется синхронный методACC_SYNCHRONIZED
Реализация тега. Следующие несколько статей будут более подробными с точки зрения исходного кода JVM, и слои будут сняты.synchronized
вуаль.
Перед входом в тему необходимо проложить некоторые базовые знания, которые необходимо проложить, поэтому давайте посмотрим на легко пропущенную, но очень важные знания - модель java объекта.
Как мы все знаем, объекты Java хранятся в куче памяти. В памяти объект Java состоит из трех частей: заголовка объекта, данных экземпляра и заполнения выравнивания. Заголовок объекта является очень важной частью, потому чтоЗаголовок объекта содержит флаг состояния блокировки, блокировку, удерживаемую потоком, и т. д.. Эта статья в основном начинается с объектной модели Java и выясняет, как заголовок объекта нашего отношения и данные времени выполнения, связанные с блокировкой в заголовке объекта, представлены в JVM.
Объектная модель Java
Любой, кто соприкасался с Java, знает, что Java — это объектно-ориентированный язык. В процессе изучения Java вы должны быть знакомы со следующими двумя предложениями:
-
1. В объектно-ориентированном программном обеспечении объект является экземпляром класса.Википедия
-
2. Все является объектомThinking In Java
Мы также знаем, что в структуре памяти JVM объекты хранятся в куче памяти, и когда мы работаем с объектами, мы фактически работаем со ссылками на объекты. Итак, какова структура самого объекта в JVM? Все анализы в этой статье основаны наHotSpotвиртуальная машина.
oop-klass model
HotSpot реализован на основе C++, а C++ является объектно-ориентированным языком, который сам по себе обладает основными характеристиками объектно-ориентированного, поэтому для представления объектов в Java проще всего сгенерировать класс C++ для каждого соответствующего ему класса Java. . Но HotSpot JVM этого не сделала, а спроектировалаOOP-Klass Model
. ООП (Ordinary Object Pointer
) относится к обычному указателю объекта, аKlass
Конкретный тип, используемый для описания экземпляра объекта.
Почему Hotspot разработал наборoop-klass model
Шерстяная ткань? Ответ таков: разработчики HotSopt JVM не хотели, чтобы каждый объект имелvtable
(виртуальная таблица функций)
Это объяснение кажется логичным. Как мы все знаем, C++ и Java являются объектно-ориентированными языками, а важной особенностью объектно-ориентированных языков является полиморфизм. С точки зрения реализации полиморфизма C++ и Java имеют существенные различия.
Полиморфизм — одна из важнейших особенностей объектно-ориентированного подхода, это динамическая привязка методов, а тип реализации определяет поведение объекта во время выполнения. Проявлением полиморфизма является то, что указатель или ссылка родительского класса указывает на объект подкласса, а метод, вызываемый для этого указателя, использует версию реализации подкласса. Полиморфизм является ключом к реализации IOC и шаблона шаблона.
В C++ полиморфизм достигается с помощью таблиц виртуальных функций.Каждый класс, содержащий виртуальные функции, имеет таблицу виртуальных функций (виртуальную таблицу), и в верхней части адресного пространства этого объекта класса находится указатель на таблицу виртуальных функций. , указатель. В таблице виртуальных функций все виртуальные функции перечислены в порядке их объявления. Поскольку C++ не поддерживает информацию о типе во время выполнения, метод, переопределяемый подклассом, заменяется непосредственно в таблице виртуальных функций подкласса во время компиляции.
В Java информация о типах и наследование классов сохраняются во время выполнения. Каждому классу будет соответствовать структура данных в области методов для хранения информации о классе, и доступ к этой структуре данных можно получить через объект класса. Среди них информация о типе имеет атрибут суперкласса, указывающий на его суперкласс, и таблицу методов, соответствующую этому классу (которая содержит только методы, определенные этим классом, исключая унаследованные от суперкласса). И каждый объект, созданный в куче, имеет указатель на структуру данных информации о типе области методов, по которой можно определить тип объекта.
Вышеприведенный абзац взят из интернета, и в нем есть какой-то смысл, но он не совсем корректен. Что касается причин, я подробнее расскажу об этом позже, когда буду представлять Klass.
Об общем определении модели opp-klass в HotSpotисходный кодможно найти в .
Модуль oops можно разделить на две относительно независимые части: фреймворк ООП и фреймворк Klass.
существуетoopsHierarchy.hppЗдесь определяются соответствующие системы oop и klass.
структура oop-класса
ой система:
//定义了oops共同基类
typedef class oopDesc* oop;
//表示一个Java类型实例
typedef class instanceOopDesc* instanceOop;
//表示一个Java方法
typedef class methodOopDesc* methodOop;
//表示一个Java方法中的不变信息
typedef class constMethodOopDesc* constMethodOop;
//记录性能信息的数据结构
typedef class methodDataOopDesc* methodDataOop;
//定义了数组OOPS的抽象基类
typedef class arrayOopDesc* arrayOop;
//表示持有一个OOPS数组
typedef class objArrayOopDesc* objArrayOop;
//表示容纳基本类型的数组
typedef class typeArrayOopDesc* typeArrayOop;
//表示在Class文件中描述的常量池
typedef class constantPoolOopDesc* constantPoolOop;
//常量池告诉缓存
typedef class constantPoolCacheOopDesc* constantPoolCacheOop;
//描述一个与Java类对等的C++类
typedef class klassOopDesc* klassOop;
//表示对象头
typedef class markOopDesc* markOop;
Выше приведена композиционная структура всего модуля Oops, который содержит несколько подмодулей. Каждый подмодуль соответствует типу, а ООП каждого типа представляет тип конкретного объекта, используемого внутри JVM.
Как видно из приведенного выше кода, существует переменная opp, тип которойoppDesc
, общий базовый тип класса OOPS:oopDesc
.
**В процессе выполнения Java-программы каждый раз, когда создается новый объект, соответственно в JVM будет создаваться ООП-объект соответствующего типа. **В HotSpot есть несколькоoopDesc
подкласс . КромеoppDesc
Кроме типа, в системе опп есть еще многоinstanceOopDesc
,arrayOopDesc
и другие типы экземпляров, они обаoopDesc
подкласс .
Эти OOPS по-разному используются внутри JVM, например **,instanceOopDesc
представляет экземпляр класса,arrayOopDesc
представляет собой массив. **То есть,когда мы используемnew
При создании экземпляра объекта Java JVM создаетinstanceOopDesc
объект для представления этого объекта Java. Точно так же, когда мы используемnew
При создании экземпляра массива Java JVM создаетarrayOopDesc
объект для представления этого объекта массива.
В HotSpot класс oopDesc определен вoop.hppINSTOMOPDESC определениеinstanceOop.hppОпределение МАССИВАОПДЕСКarrayOop.hppсередина.
Просто взгляните на соответствующие определения:
class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
union _metadata {
wideKlassOop _klass;
narrowOop _compressed_klass;
} _metadata;
private:
// field addresses in oop
void* field_base(int offset) const;
jbyte* byte_field_addr(int offset) const;
jchar* char_field_addr(int offset) const;
jboolean* bool_field_addr(int offset) const;
jint* int_field_addr(int offset) const;
jshort* short_field_addr(int offset) const;
jlong* long_field_addr(int offset) const;
jfloat* float_field_addr(int offset) const;
jdouble* double_field_addr(int offset) const;
address* address_field_addr(int offset) const;
}
class instanceOopDesc : public oopDesc {
}
class arrayOopDesc : public oopDesc {
}
Как видно из исходного кода выше,instanceOopDesc
на самом деле унаследовалoopDesc
, и никакие другие структуры данных не были добавлены, т.е.instanceOopDesc
В основном он включает в себя следующие части данных:markOop _mark
а такжеunion _metadata
и некоторые другие видыfield
.
В виртуальной машине HotSpot расположение объектов, хранящихся в памяти, можно разделить на три области: заголовок объекта, данные экземпляра и заполнение выравнивания. Внутри виртуальной машины объект Java соответствуетinstanceOopDesc
Объект. Заголовок объекта состоит из двух частей:_mark
а также_metadata
, хотя данные экземпляра хранятся в различных полях, определенных в OOPDESC.
_mark
Как мы сказали в начале статьи, мы хотим написать эту статью потому, что в заголовке объекта есть данные времени выполнения, связанные с блокировками.synchronized
и важная основа для других типов реализации блокировки, а информация о метках блокировки, генерации GC и т. д. хранится в_mark
середина. Поскольку эта статья в основном знакомитoop-klass
Модель, мы пока не будем расширять заголовок объекта, который будет представлен в следующей статье.
_metadata
упомянутый ранее_metadata
это сообщество, из которого_klass
обычный указатель,_compressed_klass
является сжатым указателем класса. Прежде чем углубляться, мы подойдем кoop-Klass
другой главный геройklass
.
klass
система классов
//klassOop的一部分,用来描述语言层的类型
class Klass;
//在虚拟机层面描述一个Java类
class instanceKlass;
//专有instantKlass,表示java.lang.Class的Klass
class instanceMirrorKlass;
//专有instantKlass,表示java.lang.ref.Reference的子类的Klass
class instanceRefKlass;
//表示methodOop的Klass
class methodKlass;
//表示constMethodOop的Klass
class constMethodKlass;
//表示methodDataOop的Klass
class methodDataKlass;
//最为klass链的端点,klassKlass的Klass就是它自身
class klassKlass;
//表示instanceKlass的Klass
class instanceKlassKlass;
//表示arrayKlass的Klass
class arrayKlassKlass;
//表示objArrayKlass的Klass
class objArrayKlassKlass;
//表示typeArrayKlass的Klass
class typeArrayKlassKlass;
//表示array类型的抽象基类
class arrayKlass;
//表示objArrayOop的Klass
class objArrayKlass;
//表示typeArrayOop的Klass
class typeArrayKlass;
//表示constantPoolOop的Klass
class constantPoolKlass;
//表示constantPoolCacheOop的Klass
class constantPoolCacheKlass;
а такжеoopDesc
Подобно родительскому классу других типов oop, класс Klass является родительским классом для других типов klass.
Klass предоставляет JVM две функции:
- Реализовать классы Java на уровне языка (уже реализованные в базовых классах Klass)
- Реализовать функцию распределения объектов Java (реализуется виртуальными функциями, предоставляемыми подклассами Klass)
В начале статьи я сказал: Причина в конструкцииoop-klass
модели, потому что разработчики HotSopt JVM не хотели, чтобы каждый объект имел в себе виртуальную таблицу.
Дизайнеры JVM Hotspot разделили объект на два, разделенные на дваklass
а такжеoop
,вoop
Функция в основном предназначена для представления данных экземпляра объекта, поэтому она не содержит никаких виртуальных функций. Для достижения полиморфизма виртуальных функций класс предоставляет таблицу виртуальных функций. Поэтому что касается полиморфизма в Java, то на самом деле существуют тени виртуальных функций.
_metadata
это сообщество, из которого_klass
обычный указатель,_compressed_klass
является сжатым указателем класса. Оба указателя указывают наinstanceKlass
Объект, который используется для описания конкретного типа объекта.
instanceKlass
JVM нужен механизм для идентификации внутренних типов Java во время выполнения. Решение в HotSpot таково: для каждого загруженного класса Java создайтеinstanceKlass
Объект, используемый для представления классов Java на уровне JVM.
посмотриinstanceKlassВнутренняя структура:
//类拥有的方法列表
objArrayOop _methods;
//描述方法顺序
typeArrayOop _method_ordering;
//实现的接口
objArrayOop _local_interfaces;
//继承的接口
objArrayOop _transitive_interfaces;
//域
typeArrayOop _fields;
//常量
constantPoolOop _constants;
//类加载器
oop _class_loader;
//protected域
oop _protection_domain;
....
Как видите, здесь есть все, что должно быть в классе.
Вот еще один момент, о котором следует кратко рассказать.
В JVM основной формой существования объектов в памяти является oop. Затем класс, к которому принадлежит объект, также является объектом в JVM, поэтому они фактически организованы в своего рода oop, а именно klassOop. Точно так же для klassOop также существует соответствующий класс для описания, которым является klassKlass, который также является подклассом класса. klassKlass служит конечной точкой цепочки классов oop. Цепочка классов объектов и массивов выглядит примерно так:
При таком дизайне JVM может управлять выделением и восстановлением памяти унифицированным образом. Связь между oop-klass-klassKlass показана на рисунке:
хранение памяти
Относительно хранения Java-объекта многие обычно ответят: объект хранится в куче. Человек чуть получше ответил бы: Объекты хранятся в куче, а ссылки на объекты хранятся в стеке. Сегодня я дам вам еще более удивительный ответ:
Экземпляр объекта (instantOopDesc) хранится в куче, метаданные объекта (instantKlass) хранятся в области методов, а ссылка на объект хранится в стеке.
На самом деле, если вы внимательно исследуете это, приведенное выше предложение немного преднамеренно хвастается. Потому что мы все это знаем.Область методов используется для хранения таких данных, как информация о классе, константы, статические переменные и код, скомпилированный компилятором JIT, загружаемым виртуальной машиной.Так называемая информация о загруженном классе на самом деле означает, что объект InstantKlass создается для каждого загруженного класса.
Разговоры дешевы, покажите мне код:
class Model
{
public static int a = 1;
public int b;
public Model(int b) {
this.b = b;
}
}
public static void main(String[] args) {
int c = 10;
Model modelA = new Model(2);
Model modelB = new Model(3);
}
Структура хранилища следующая:
Как видно из рисунка выше, естьint a=1
хранилище данных. В oop два объекта в куче памяти соответственно сохраняемint b=3
,int b=2
данные экземпляра. Как и oopDesc, InstantKlass поддерживает некоторыеfields
, используемый для сохранения данных класса, определенных в классе, таких какint a=1
.
Суммировать
Для каждого класса Java при загрузке JVM JVM создаетinstanceKlass
, хранящийся в области методов и используемый для представления класса Java на уровне JVM. Когда мы используем new для создания объекта в коде Java, JVM создастinstanceOopDesc
Объект, этот объект содержит две части информации, заголовок объекта и метаданные. В заголовке объекта есть некоторые данные времени выполнения, включая информацию о блокировках, связанных с многопоточностью. Метаданные фактически содержат указатели на класс, к которому принадлежит объект.instanceKlass
.
использованная литература
[Понимание виртуальной машины HotSpot] Представление объектов в JVM: модель ООП-класса
Отражение Java: подробное объяснение полной ссылки от JDK к JVM