Предисловие:
Здравствуйте, доброе утро, полдень, день, вечер. Я брат Java2B (поиск Wechat Java2B). Пропущенный 985, ежедневный 996 инженер. Вы очень взволнованы!
Сегодня Brother 2B продолжит обучать вас знанию JVM. Эта глава: Предыдущая статья: [Gold Three Silver Four — серия JVM] Подробное объяснение сборщика CMS и анализа журнала GC и проблемы с позиционированиемnuggets.capable/post/684490…
[Золотая тройка Серебряная четверка] Подробное объяснение виртуальной машины JVM CMS и коллектора G1nuggets.capable/post/684490…
что такое JVM
Я полагаю, что многие мелкие партнеры хорошо знакомы с ним Разве JVM не виртуальная машина? Тогда что такое виртуальная машина? Не JVM! Это не чепуха.
JVM можно сказать и знакомая и незнакомая нам, многие знакомые могут не иметь доступа к этой технологии на работе, но их часто спрашивают на собеседованиях (вероятность достаточно высока), а когда спрашивают, то признаются, что они не везет, а зазубривание бесполезно.Да я еще забыл в итоге, но это не беда, сегодня вы встречаетесь с братом 2B и я, я вам бесплатно расскажу о очках знаний JVM, если не позволю ты понимаешь, что я неудачник, ты можешь оставить сообщение и побрызгать меня, если сможешь, ты тоже поставишь мне палец вверх? Хватит рисовать, поторопитесь.
ок, запасайся. Здесь должны быть цветы! ❀❀❀❀❀❀❀❀
Первое знакомство с JVM:
Думаю, эта картина знакома всем: это вся система Java, включая связь между JDK, JRE и JVM.
Из рисунка видно, что JRE содержит JVM, а JDK содержит JRE.
С точки зрения включения: JDK — дедушка JRE — отец JVM — сын (если вы считаете, что это неуместно), посмотрите на картинку
Давайте посмотрим на код:
public class App {
private String name;
private Object object = new Object();
/***
* 运算
*/
public int add() {
int a = 1;
int b = 2;
int c = (a + b) * 100;
return c;
}
/**
* 程序入口
*/
public static void main(String[] args) throws InterruptedException {
App app = new App();
int result = app.add();
System.out.println(result);
}
}
Когда мы запускаем приведенный выше код, выходной результат равен 300. Хотя этот код очень прост, в это время были задействованы знания, связанные с JVM.Когда мы изучали основы Java, учитель сказал нам, что Java является кросс- платформе, и его можно написать один раз и запускать везде.
Так как же Java достигает кросс-платформенности? Продолжайте смотреть на картинку ниже:
Из этого изображения нетрудно понять, что скомпилированный нами файл App.class может работать в операционной системе Windows или в системе Linux, но базовые инструкции по эксплуатации этих двух систем различаются. , start Для кроссплатформенной роли JVM незаменима Мы часто говорим, что Java является кроссплатформенной, а не кроссплатформенной JVM (кроссплатформенная среда выполнения JRE). Насколько кроссплатформенна виртуальная машина JVM?
Основной принцип JVM:
Нижний уровень JVM состоит из трех систем: загрузки классов, области данных времени выполнения и механизма выполнения.
Сегодня мы сосредоточимся на области данных времени выполнения JVM (стеке), а два других могут быть посвящены моим предыдущим и последующим статьям.
Наш файл App.class считывает файл с жесткого диска и загружает его в память (область данных времени выполнения) через подсистему загрузки классов.
Что делать после завершения загрузки? (По аналогии, люди едят "в желудок" каждый орган отвечает за свою работу и всасывание)
Стек стека:
Давайте поговорим об одном из стеков области памяти виртуальной машины.Всем известно, что стек — это структура данных и область, уникальная для потоков, то есть у каждого потока будет своя независимая область стека. Мы запускаем App.java для вывода 300 в зависимости от результата выполнения потока. Какой поток его выполняет? Получить снимок потока: "основной поток"
Стек, структура данных, содержимое хранилища, первый пришел, последний ушел FILO
Все мы знаем, что у каждого метода есть свои локальные переменные, такие как результат в основном методе на рисунке выше, abc в методе добавления, затем виртуальная машина java, чтобы различать область памяти области действия локального переменная в разных методах, каждый метод Во время выполнения выделяется отдельная область памяти кадра стека.Попробуем просто нарисовать активность памяти выполнения кода по программе на рисунке выше.
Первая строка кода при выполнении основного метода заключается в том, что стек выделит кадр стека метода main() и сохранит локальную математическую переменную, а затем выполнит метод add(), после чего стек выделит стек область кадра метода add().
Стек здесь хранит данные так же, как стек, изученный в структуре данных, первый вошел, последний вышел. Когда метод add() выполняется, он извлекается из стека и освобождается, что соответствует характеристикам «первым пришел — последним вышел», а метод, вызванный позже, выскочит из стека первым.
кадр стека:
Внутренняя «структура данных» кадра стека в основном состоит из следующих частей: таблицы локальных переменных, стека операндов, выхода метода и другой информации.
После долгого разговора, для чего используется кадр стека? Не беспокойтесь об этом, здесь будет задействован принцип более низкого уровня — байт-код. Давайте сначала посмотрим на файл байт-кода нашего кода выше.
Файл APP.class выглядит как искаженные символы. На самом деле каждый из них имеет соответствующее значение. У Oracle официально есть специальное руководство по использованию байт-кода jvm для запроса значения каждой группы инструкций. Это не то, что мы изучаем, конечно.
JDK имеет собственную команду javap, которая может генерировать более читаемый файл байт-кода из указанного выше файла класса.
Compiled from "App.java"
public com.App {
public com.App();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."<init>":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
public int add();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 100
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
Code:
0: new #4 // class com/App
3: dup
4: invokespecial #5 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #6 // Method add:()I
12: istore_2
13: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #8 // Method java/io/PrintStream.println:(I)V
20: return
}
В настоящее время код инструкций jvm намного понятнее, и можно понять общую структуру, такую как классы, статические переменные, методы построения, методы add() и методы main(). Инструкции в методе все еще немного запутаны, давайте взглянем на метод add():
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 100
9: imul
10: istore_3
11: iload_3
12: iretu
Эти строки кода соответствуют четырем строкам кода в методе add() в нашем коде. Все мы знаем, что чем ниже уровень кода, тем больше строк реализует код, потому что он будет содержать некоторые детали и принципы, которые скрыты внизу java-кода во время выполнения. Так же, у этой официальной команды jvm также есть руководства, с которыми можно ознакомиться, и в Интернете есть много версий перевода.Если вы хотите узнать больше, вы можете Baidu.
Процесс реализации:
Значение некоторых инструкций в коде дизайна:
Первый шаг: нажмите на стек:
Поместите константу 1 типа int в стек операндов.
0: iconst_1
это поместить 1 в стек операндов
Шаг 2: Магазин:
Сохранить значение типа int в локальной переменной 1
1: istore_1 Локальная переменная 1, которая является первой локальной переменной a в нашем коде, сначала выделяет память для a в таблице локальных переменных, а затем сохраняет значение типа int, которое в настоящее время является единственным 1, в локальную переменную a
Шаг 3: Назначение
Эти две строки кода аналогичны первым двум строкам.
2: iconst_2 3: istore_2
Шаг 4: Загрузите:
Загрузить значение типа int из локальной переменной 2
4: iload_1 5: iload_2 Эти два кода загружают локальные переменные 1 и 2, то есть значения a и b, в стек операндов
Шаг 5: Добавление
выполнить добавление типа int
6: иадд После выполнения инструкции iadd числа 1 и 2 в стеке операндов будут извлечены из нижней части стека и добавлены по очереди, а затем результат операции 3 будет помещен в нижнюю часть стека операндов.
Шаг 6: Нажмите стек:
Поместите 8-битное целое число со знаком в стек
7: бипуш 100 Эта инструкция помещает 100 в стек
Шаг 7: Умножение:
выполнить умножение типа int
9: имул Это похоже на описанное выше добавление, извлекающее 3 и 100 из стека и помещающее результат 300 в стек.
Шаг 8: Нажмите стек:
сохранит значение типа int в локальной переменной 3
10: istore_3 Это всем здесь знакомо, это то же самое, что и второй шаг, и третий шаг, сохраните 300 в локальной переменной 3, которая равна c
Шаг 9: Загрузка:
Загрузить значение типа int из локальной переменной 3
11: iload_3 Загрузка из локальной табличной переменной 3 в стек операндов
Шаг 10: Вернитесь к:
возвращаемое значение типа int
12: ireturn
Наш метод add вызывается основным методом, поэтому возвращаемся к методу хранения переменной результата в методе mian через выход из метода, грубо говоря, выход это то место, куда попадет метод после выполнения метода, тогда мы знайте, что описанный выше метод add() должен быть выполнен после выполнения.Вернитесь к третьей строке метода main(), затем, когда метод main() вызывает add(), метод завершается в кадре стека add() сохраняет текущую позицию, в которую нужно вернуться, затем, когда метод add() завершит выполнение, он вернется в соответствующую позицию метода main() в соответствии с соответствующей информацией, хранящейся в выходе метода. Посмотрите на красную линию на моей картинке
Отношения стека:
В дополнение к переменной результата в основном методе есть переменная приложения, и переменная приложения указывает на объект. Как хранится объект? Здесь я хочу рассказать о структуре локальной таблицы переменных table: базовые типы и ссылочные типы (Java называется эталонным, C++ называется указателем)
Отношения:
Ссылайтесь на объект приложения в куче, ссылаясь на переменную приложения в стеке.
Суммировать:
На данный момент я полагаю, что все знакомы с принципом выполнения стека JVM? Если вам это нравится, пожалуйста, ставьте лайк и комментируйте. Оригинальность – это не просто
Если вы считаете, что статья автора хороша, обратите внимание на мой WeChat: Java2B (инженер Daily 996).
Исправление: в процессе выполнения серый фон «стек операндов» должен быть заменен на «таблицу локальных переменных».