在阅读JVM规范时(正如一样),当我遇到7个iconst_<i>
操作码时,我感到非常惊讶。毕竟,只有一个字节可供使用。
我很少在代码中写入2,3,4或5的文字。我可以理解为什么-1,0和1可能会被特别对待,但我觉得设计师想要将4个宝贵的操作码放在恰好相当小的数字上似乎很神奇。
有谁知道这是否有充分理由?我低估了这些的好处吗?
答案 0 :(得分:4)
我认为,你的假设是正确的:只是让字节码更小,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
。
答案 1 :(得分:3)
希望这可以澄清你的问题为什么浪费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个字节。
因此,对于一些常被推送的数字,定义了这样的字节码 提高字节码执行效率,减小字节码大小 字节码流。
正如Tagir所说,这些数字会比你想象的更频繁地使用