Почему у JVM есть коды операций iconst_2 - iconst_5?
Читая спецификацию JVM (как это делают), я был очень удивлен, когда наткнулся на 7 iconst_<i>
опкоды. В конце концов, есть только один байт для игры.
Я очень редко пишу литералы для 2, 3, 4 или 5 в моем коде. Я могу понять, почему с -1, 0 и 1 можно обращаться особым образом, но мне кажется удивительным, что дизайнеры хотели бы использовать 4 драгоценных кода операции для чисел, которые оказались очень маленькими.
Кто-нибудь знает, есть ли для этого веская причина? Я недооцениваю выгоду от них?
2 ответа
Я думаю, ваше предположение верно: просто сделать байт-код меньше, а Java-интерпретатор чуть-чуть быстрее (в те времена не было JIT-компилятора). Обратите внимание, что эти байт-коды могут использоваться гораздо чаще, чем вы ожидаете. Например, рассмотрим следующий код:
int[] a = {10, 20, 30, 40};
По сути это скомпилировано в нечто вроде:
int[] a = new int[4];
a[0] = 10;
a[1] = 20;
a[2] = 30;
a[3] = 40;
Так вот iconst_0
в iconst_4
используются, даже если у вас нет таких констант в исходном коде.
Надеюсь, что это может прояснить ваш вопрос Зачем тратить 4 кода операции..
Посмотрите Байт-код этого кода
public static void main(String[] args) {
int b = 20;
int c = 5;
int d= 6;
}
часть байт-кода
0: bipush 20
2: istore_1
3: iconst_5
4: istore_2
5: bipush 6
7: istore_3
Как вы можете видеть для номера больше 5, он начинает использовать bipush
которые обычно менее эффективны, чем эквивалент iconst_<n>
а также занять больше байтов в файле класса.
bipush
byte1
раскрыватьсяbyte1
в int, а затем помещает его в стек, потому что каждый слот в стеке Java имеет ширину 32 бита (JVM - это виртуальные машины на основе стека)
И посмотреть, если bipush
занимает больше байта..
Посмотрите размер файла класса в двух следующих кодах (этот размер на моем 64-битном компьютере.. он может отличаться на вашем компьютере, но разница будет такой же)
public class Test2 {
public static void main(String[] args) {
int b = 5;
}
}
размер 406 байт
сейчас, если я заменю b =6
; размер файла того же класса становится 407 bytes
который остается постоянным, даже когда b=127
который также использует bipush
, Это различие в размере связано с тем, что bipush имеет 2 байта, один байтовый код операции, второе байтовое значение constat.
формат bipush:
bipush
byte
как вы можете видеть из строки 5: bipush 6
в байт-коде в то время как iconst_<n>
использует только 1 байт.
Таким образом, такие байт-коды определены для некоторых обычно выдвигаемых чисел, чтобы повысить эффективность выполнения байт-кода и уменьшить размер потоков байт-кода.
и, как сказал Тагир, эти цифры будут использоваться чаще, чем вы думаете