Глубокое понимание многопоточности (2) — объектная модель Java

Java задняя часть JVM C++

ПредыдущийКратко представлено в статье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

ой система:

//定义了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подкласс .

OOP结构

Эти 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

Klass предоставляет JVM две функции:

  • Реализовать классы Java на уровне языка (уже реализованные в базовых классах Klass)
  • Реализовать функцию распределения объектов Java (реализуется виртуальными функциями, предоставляемыми подклассами Klass)

В начале статьи я сказал: Причина в конструкцииoop-klassмодели, потому что разработчики HotSopt JVM не хотели, чтобы каждый объект имел в себе виртуальную таблицу.

Дизайнеры JVM Hotspot разделили объект на два, разделенные на дваklassа такжеoopoopФункция в основном предназначена для представления данных экземпляра объекта, поэтому она не содержит никаких виртуальных функций. Для достижения полиморфизма виртуальных функций класс предоставляет таблицу виртуальных функций. Поэтому что касается полиморфизма в 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. Цепочка классов объектов и массивов выглядит примерно так:

400_ac3_932

При таком дизайне JVM может управлять выделением и восстановлением памяти унифицированным образом. Связь между oop-klass-klassKlass показана на рисунке:

2579123-5b117a7c06e83d84

хранение памяти

Относительно хранения 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);
}

Структура хранилища следующая:

20170615230126453

Как видно из рисунка выше, есть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.

we

использованная литература

[Понимание виртуальной машины HotSpot] Представление объектов в JVM: модель ООП-класса

Отражение Java: подробное объяснение полной ссылки от JDK к JVM

Анализ реализации объектного механизма HotSpotVM #1

Горячая точка в действии