Требуется некоторое время, чтобы понять байт-код JVM.Для того, чтобы вы начали здесь две вещи, которые вы должны знать:
Виртуальная машина Java является стек машины: когда необходимо оценить выражение его первый выталкивает входы Выражение в в стеке, а затем оценка выражения по существу, выталкивая все входы из стека и возвращая результат обратно в верхнюю часть стека. этот результат, в свою очередь, может быть использован как вход для оценки другого выражения.
Все параметры и локальные переменные хранятся в локальном массиве переменных.
Давайте посмотрим, что на практике. Вот исходный код:
package p1;
public class Movie {
public void setPrice(int price) {
this.price = price;
}
}
Как сказал EJP, вы должны запустить javap -c, чтобы увидеть байткод: javap -c bin/p1/Movie.class
. Это выход:
public class p1.Movie {
public p1.Movie();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: return
public void setPrice(int);
Code:
0: aload_0
1: iload_1
2: putfield #18 // Field price:I
5: return
}
Глядя на выходе вы можете увидеть, что в байт-код, мы видим, конструктор по умолчанию, а метод setPrice
.
Первая инструкция, aload_0
принимает значение локальной переменной 0 и толкает ее в стек (complete list of instructions). В не статический метод, локальная переменная 0, всегда параметр this
так после инструктажа 0 наш стек
| this |
+------+
Следующая инструкция aload_1
которая принимает значение локальной переменной 1 и толкает его в стек. В нашей локальной переменной 1 указан параметр метода (цена). Наш стек теперь выглядит следующим образом:
| price |
| this |
+-------+
Следующая команда putfield #18
это один делает назначение this.price = price
. Эта команда извлекает два значения стека. Первое всплывающее значение - это новое значение полей. Второе всплывающее значение - это указатель на объект, которому присвоено поле. Имя назначаемого поля закодировано в инструкции (поэтому инструкция берет три байта: она начинается в позиции 2, но следующая инструкция начинается в позиции 5). Дополнительное значение, закодированное в инструкции, равно «# 18». Это индекс в постоянный пул. Чтобы увидеть постоянный пул, вы должны запустить: javap -v bin/p1/Movie.class
:
Classfile /home/imaman/workspace/Movie-shop/bin/p1/Movie.class
...
Constant pool:
#1 = Class #2 // p1/Movie
...
#5 = Utf8 price
#6 = Utf8 I
...
#18 = Fieldref #1.#19 // p1/Movie.price:I
#19 = NameAndType #5:#6 // price:I
...
Так #18
указывает, что поле для назначения является price
поле p1.Movie
класса (как вы можете видеть, # 18 делает ссылки на # 1, # 19 которые, в свою очередь, ссылаются на № 5 и № 6. Фактическое имя назначенного поля отображается в пуле констант)
назад к нашему исполнению команды putfield
: выставив два значения из стека, JVM теперь назначает сначала всплыло в поле price
(указано #18
) this
(второе значение).
Оценочный стек теперь пуст.
Последняя инструкция просто возвращается.
Попробуйте выполнить команду 'javap -c'. Некоторые из них не имеют смысла. Переменные не «прыгают» нигде, и для этого не требуется последовательное выполнение. – EJP
Возможно, вы хотите начать чтение [Спецификация виртуальной машины Java®] (http://docs.oracle.com/javase/specs/jvms/se8/html/index.html), особенно [§4. Формат файла класса] (http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html) и [§6. Набор инструкций виртуальной машины Java] (http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html) – Holger