Объяснение
Все, что делает Java под капотом, полностью скрыто от пользователя и программиста.
Пока вы все еще пишете код Java, с ним невозможно связываться. Конечно, это может быть другая история, если вы попытаетесь подключить процесс JVM и внедрить код C или взаимодействовать с ним через его собственный интерфейс.
Это также полностью зависит от JVM, как он фактически обрабатывает это в памяти,Управление памятью полностью скрыто от программиста на Java.
Байт-код
Переменная встроенная
При этом давайте посмотрим на результирующий байт-код дляэтот фрагмент (см. javabytes.io или используйте javap -c Test.class
):
// Source code
public class Test {
public static void main(String [] args) {
int value = 4000;
System.out.println(value);
System.out.println(5678);
}
}
// Byte code
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: sipush 4000
3: istore_1
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: iload_1
8: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
11: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
14: sipush 5678
17: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
20: return
}
Как видите, оба варианта на самом деле одинаковы. Команда sipush
загружает значения напрямую, без каких-либо признаков каких-либо переменных.
sipush
помещает short
непосредственно в стек, откуда оно затем берется invokevirtual
, которыйвызывает метод print (подробнее см. список инструкций Java bytecode ).
Почему это так? Ну, компилятор умный. Он понял, что переменная value
не имеет смысла, и фактически полностью избавился от нее. Он изменил код на System.out.println(4000)
и полностью удалил value
.
Присутствует переменная
Но мы хотим увидеть некоторые переменные, поэтому давайте сделаем это немного сложнее, чтобы Java это делалабольше не вставляйте переменную в строку, вводя зависимость, которая может быть вычислена только во время выполнения:
// Source code
public class Test {
public static void main(String [] args) {
int value = (int) System.currentTimeMillis();
System.out.println(value);
System.out.println(5678);
}
}
// Byte code
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
3: l2i
4: istore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: iload_1
9: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
15: sipush 5678
18: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
21: return
}
Наконец, мы видим действие переменной! Переменная вычисляется методом, преобразуется в int
и затем сохраняется с помощью istore_1
. Затем он динамически загружается в стек с помощью iload_1
и передается методу печати.
Таким образом, через переменную нам нужно istore
и iload
его методу. С помощью литерала мы можем напрямую загрузить его в метод, используя sipush
.