Jvmmemorymodel
Эта статья в основном представляет область данных времени выполнения (Runtimedataareas), описанная в спецификации JVM. Эти области предназначены для хранения данных, используемых самими JVM или программами, работающими на JVM.
Давайте сначала обзор JVM, затем введем байт -код и, наконец, введем различные области данных.
Обзор
В качестве абстракции операционной системы JVM гарантирует, что один и тот же код ведет себя последовательно на различных оборудовании или операционных системах.
например:
Для базового типа INT это 32-разрядное подписанное целое число независимо от 16-битной/32-битной/64-битной операционной системы. Диапазон от -2^31 до 2^31-1
Независимо от того, является ли операционная система или аппаратное обеспечение большим или малым байтовым порядком, гарантируется, что данные в памяти, хранящихся и используемые JVM, являются большим или небольшим байтовым порядком (сначала прочитайте байт с высоким содержанием))
Различные реализации JVM могут несколько отличаться, но, как правило, одинаковы.
Приведенная выше картина представляет собой обзор JVM
JVM интерпретирует сгенерированный компилятором байт-код. Хотя JVM является аббревиатурой виртуальных машин Java, если он является языком, который можно скомпилировать в байт -код, его можно запустить на основе JVM, такой как Scala, Groovy <� »/KF/Ware/VC/" target = "_ Blank"> VCD4NCJXWPS6QWCUX3MPIXRW3SBXETMXFZEKVT6OS19A92SLRU+GXU2NSYXNZBG9HZGVYVNPU2LKIU7Q05R W91MVQ0MQXYV2+3CF41TC1XNK7UPBH+NPYOO6ZWQRXAVNPU2MV8TCRJBGFZC2XVYWRLCRG7Z/Q72BVY1D9KVK3NO9A51MVQ0KGJPC 9WPG0KPHA+VNPU2LXE19A92SLRZAI5/DA00NDS/CFMKGV4ZWN1DGLVBIBLBMDPBMUPVFJQ0L3IYS26ZDA00NA8L3A+DQO8CD7WT Ndq0v3h5tdo0qq05rsis8zq8snpz8loxkosscji57pm0plwtndqtb3exnk70ncjrlvy1d/k/b7dvmbl47xe1tc85l3hufs8l3a+d QO8CD7WTNDQ0V3H5TKYULRU8LSMWO3T67XXSUOY2DF3Z7XNS7XEVBU7PTWVCD4NCJXWPIOQUTY24EPWTBA8YRXP1SHLLTKSBHG 0UU5PSTCKEPJVD1QDXN0IGLUIHRPBWUPOANKSVS+ZCRHSNG+RBOJ1RTQ0LXETPRC6YJIYLXJTPRC6YMX4NLRS8MXVRXYTPRC6YHO YXRPDMUGQ29KZSMHO7TMT8VKSVSX4NLRYFQUSIBT6WUU1XMF40/KZXS6QPC9WPG0KPHA+TPRC67U6TOBH+CHDB2RLIENH Y2GPOAO8TMQXSEDS67Y8YVUOSKLUKBY2TPO1XMZHUN/BY0PWTBXE0NTE3COQPC9WPG0KPGGYIGLKPQ == " Архитектура »> Архитектура на основе стека
JVM использует архитектуру на основе стека. Хотя стек прозрачен для разработчиков, он играет очень важную роль или влияние на генерируемые байт -кодовые и JVM.
Разработанные нами программы будут преобразовать операции низкого уровня и хранить их в байт-коде. На карту к инструкциям по эксплуатации через операнды в JVM. Согласно спецификации JVM, параметры, требуемые инструкциями по эксплуатации, получены из стека операнда.
Давайте приведем пример добавления двух чисел. Эта операция называется IADD. Ниже приведен процесс 3+4 в байт -коде
Сначала толчок 3 и 4 в стек операнда
Позвоните в Директиву IADD
Инструкция IADD появляется на 2 номера из верхней части стека операнда
Результат 3+4 проткнута в стек операнда для последующего использования
Этот подход называется архитектурой на основе стека. Существуют и другие способы обработки низкоуровневых операций, таких как архитектура на основе регистра.
Байт -код
Java Bytecode является результатом преобразования исходного кода Java в серию низкоуровневых операций. Каждая операция состоит из OPCODE или операционного кода с параметрами нуля или более байтов (но большинство операций используют параметры, полученные через стек операнда). Один байт может представлять 256 чисел, от 0x00 до 0xff, и в настоящее время в Java8 используются в общей сложности 204.
Следующие перечислены различные типы выборов байт -кодов, а также их диапазон и простое описание
Константы: увеличить значение постоянного пула или известного значения в стек операнда. 0x00 - 0x14
Нагрузки: встаньте локальные значения переменной в стек операнда. 0x15 - 0x35
С магазина: Значение загрузки из стека операнда в локальную переменную 0x36 - 0x56
Стек: процесс операндерного стека 0x57 - 0x5f
Математика: получить значение из стека операнда для базового математического расчета 0x60 - 0x84
Конверсии: конвертировать между типами 0x85 - 0x 93
Комапризоны: Сравнение работы двух значений 0x94 - 0xa6
Элементы управления: выполнять Goto, return, gloop и т. Д. Операции управления 0xa7 - 0xb1
Список литературы: выполняет объекты распределения или массивы, а также получает или проверяет ссылки на объекты, методы и статические методы. Статические методы также можно назвать. 0xb2 - Oxc3
Расширен: расширен: операции из других категорий, которые были добавлены после. От значения от 0xc4 до 0xc9
(Что означает это предложение?
Зарезервировано: в реализации JVM используются слоты 0xca, oxfe, oxff
Эти 204 операции очень просты, приведите несколько примеров
IFEQ (0x99) определяет, равны ли два значения
IADD (0x60) добавляет два числа
i2L (0x85) преобразует немного длиной
Arraylength (0xbe) возвращает длину массива
POP (0x57) POP Значение из вершины стека операнда
Нам нужен компилятор для создания файлов Bytecode, а стандартный Java Compiler - Javac в JDK.
открытый тест класса {public static void main (string [] args) {int a = 1; int b = 15; int result = add (a, b); } public static int add (int a, int b) {int result = a + b; результат возврата; }}Вы можете получить файл Bytecode «test.class» через "Javac test.java". Файлы Bytecode являются двоичными, мы можем преобразовать двоичные файлы Bytecode в текстовую форму через Javap
java -вербоуз -тест. Класс
Classfile /c://tmp/test.class Последний модифицированный 1 Avr. 2015; Размер 367 байт MD5 Checksum ADB9FF75F12FC6CE1CDDE22A9C4C7426 Скомпилирован из "test.java" Общедоступный класс com.codinggeek.jvm.test sourcefile: "test.java" Миночная версия: 0. java/lang/object. "<int>" :() V #2 = methodRef #3. #16 // com/codinggeek/jvm/test.add: (ii) i #3 = класс #17 // com/codinggeek/jvm/test #4 = class #18 // java/lang/obj LineNumberTable #9 = UTF8 Main #10 = UTF8 ([ljava/lang/string;) V #11 = UTF8 ADD #12 = UTF8 (II) I #13 = UTF8 SourceFile #14 = utf8 test.java #15 = nameAndType #5: #6 // "IINT>" :() V #16 = NAMEANTPE #5: #5: #5: #5: #5: # #17 = utf8 com/codinggeek/jvm/test #18 = utf8 java/lang/object {public com.codinggeek.jvm.test (); Флаги: ACC_PUBLIC CODE: Stack = 1, локалы = 1, args_size = 1 0: aload_0 1: infokespecial #1 // Метод Java/Lang/Object. "<Itin>" :() V 4: return Linenumbertable: строка 3: 0 Public Static Void Main (java.lang.String []); Флаги: acc_public, acc_static Code: Stack = 2, локалы = 4, args_size = 1 0: iconst_1 1: ISTORE_1 2: Bipush 15 4: ISTORE_2 5: ILOAD_1 6: ILOAD_2 7: INVOKESTATIC #2 // Метод Добавить: (II) I 10: ISTORE_3 11: return. 9: 11 Public Static Int Add (Int, Int); Флаги: acc_public, acc_static Code: Stack = 2, locals = 3, args_size = 2 0: Iload_0 1: Iload_1 2: IADD 3: ISTORE_2 4: ILOAD_2 5: IReturn LineNumbertable: Строка 12: 0 Строка 13: 4}Видно, что ByteCode - это не просто простой перевод кода Java, он включает в себя:
Постоянное описание пула класса. Постоянные пулы - это области данных JVM, используемые для хранения метаданных классов, таких как имена методов, списки параметров и т. Д. Внутри класса. Когда JVM загружает класс, метаданные будут загружены в постоянный бассейн
Предоставьте конкретную информацию о положении функций и переменных TMALL в байт -коде через таблицу номеров строк и локальную таблицу переменных.
Перевод кода Java (включая конструкции скрытых родительских классов)
Предоставляет более конкретные операции на стеке операндов и более полные способы передачи и получения параметров
Ниже приведено простое описание информации о хранении файлов ByteCode
ClassFile {U4 Magic; u2 minor_version; U2 Major_version; u2 constant_pool_count; cp_info constant_pool [constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 интерфейсы [interfaces_count]; u2 fields_count; Field_info Fields [fields_count]; u2 attributes_count; attribute_info attributes [attributes_count];}Область данных времени выполнения
Область данных времени выполнения - это область памяти, предназначенная для хранения данных. Эти данные предназначены для использования разработчиками или JVM внутренне.
Куча
Куча создается при запуске JVM, и используется всеми потоками JVM. Все экземпляры класса и массивы выделяются на кучу (созданную новым).
Куча должна управляться коллекционером мусора, который отвечает за выпуск объектов, созданных разработчиком, и больше не будет использоваться.
Что касается стратегии сбора мусора, она определяется реализацией JVM (например, Hotspot предоставляет несколько алгоритмов).
Существует максимальный предел для памяти кучи. Если это значение будет превышено, JVM бросит исключение Outofmemroy.
Метод зона
Область метода также используется всеми потоками JVM. То же самое создано со стартапом JVM. Данные, хранящиеся в области метода, загружаются из байт -кода классовым загрузчиком, который будет постоянно существовать во время запуска приложения, если загружающий класс, загружающий их, не будет уничтожен или JVM не будет остановлен.
Область метода хранит следующие данные:
Информация о классе (имя атрибута, имя метода, имя родительского класса, имя оправдания, версия и т. Д.)
Методы и построенные байткоды
Постоянный бассейн среды выполнения, созданный при загрузке каждого класса
Спецификация JVM не заставляет области методов быть реализованы в куче. Перед Java7 в реализации методов Hotspot с использованием региона под названием PertGen. Постоянная полоса рядом с кучей (управление памятью такое же, как и куча), бит по умолчанию составляет 64 МБ.
Начиная с Java8, HPTSPOT использует отдельную локальную память для реализации области метода и названия области метаданных (MetasPace). Максимально доступное пространство в области метаданных - это доступная память всей системы.
Если метод не может применить для доступной памяти, JVM также будет выбросить OutofmemoryError.
Постоянный бассейн выполнения
Постоянный бассейн выполнения является частью области метода. Из -за важности управления постоянным пулом для метаданных он описан отдельно в спецификации Java за пределами области метода. Постоянный бассейн среды выполнения растет с загруженными классами и интерфейсами.
Постоянные бассейны являются чем -то вроде синтаксической таблицы на традиционных языках. Другими словами, когда называется класс, метод или свойство, JVM ищет реальный адрес этих данных в памяти через постоянный пул времени выполнения. Постоянный пул выполнения также содержит константы струнных литералов или примитивных типов
Fireng myString = "Это струнный букв" Статический конечный финал int my_constant = 2;
ПК (программная счетчик) Регистр (по потоку) Регистр ПК (за поток)
Каждый поток имеет свой собственный регистр ПК (счетчика программы), который создается вместе с созданием потока. Каждый поток может выполнять только один метод в момент времени, называемый текущим методом потока. Регистр ПК содержит адрес JVM, в настоящее время выполняющий инструкцию (в области метода).
Если выполняемый метод в настоящее время является локальным методом, значение регистра ПК не определена
Виртуальные машины стека на трене-java-virtual-machine-stacks-per-thread "> Стеки виртуальных машин виртуальных машин (на поток) Стеки виртуальных машин Java (на поток)
Стек виртуальных машин хранит несколько кадров, поэтому перед описанием стека давайте сначала посмотрим на кадры.
Рамы
Кадр - это структура данных, которая содержит несколько данных, представляющих текущее состояние метода, которое выполняет поток:
Стек операнда: как упоминалось ранее, инструкции по байт -коде Используйте стек операнда для передачи параметров
Локальный массив переменных: этот массив содержит все локальные переменные в рамках сфера выполненного в настоящее время метода. Этот массив может содержать примитивный тип, ссылку или обратный адрес. Размер локальной переменной массивы определяется во время компиляции. JVM использует локальные переменные для передачи параметров при вызове метода, а локальная массива переменных метода вызываемого создается через стек операнда призывного метода.
Постоянная среда выполнения. Ссылка на пул: ссылки на постоянный пул текущего метода текущего класса. JVM использует постоянные ссылки на пул для передачи сигналов в реальные ссылки на память.
Стек (стек)
Каждый поток JVM имеет частный стек JVM, который создается одновременно с потоком. Java Virtual Machine Stack хранят кадры. Каждый раз, когда называется метод, создается кадр и втягивается в стек виртуальных машин. Когда этот метод будет выполнен, кадр также будет уничтожен (независимо от того, выполняется ли метод нормально или исключено).
Только один кадр доступен во время выполнения потока. Этот кадр называется текущим кадром.
Операции на локальных переменных и стеке операндов обычно сопровождаются ссылками на текущую кадр.
Давайте посмотрим на другой пример дополнения
public int add (int a, int b) {return a + b;} public void functiona () {// какой -то код без функции call int result = add (2,3); // вызов по функции b // какой -то код без вызова функции}Внутри метод A, кадр A является текущей кадрой, расположенной в верхней части стека виртуальных машин. В начале вызова метода добавления создается новая кадра B и выдвигается в стек виртуальных машин. Кадр B становится новым текущим кадром.
Локальный массив переменных кадров B заполняется данными в стеке операнда из кадра A. Когда метод добавления заканчивается, кадр B разрушается, а кадр A восстанавливается как текущий кадр. Результат метода Добавления вставлен в стек операндов кадра A, чтобы метод A мог получить результат ADD через стек операндов кадра A.
Суммировать
Выше всего посвящено анализу областей данных времени выполнения виртуальной машины Java. Я надеюсь, что это будет полезно для всех.
Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это.