为什么JVM有iconst_2 - iconst_5操作码?

时间:2015-06-09 23:32:39

标签: java jvm opcodes

在阅读JVM规范时(正如一样),当我遇到7个iconst_<i>操作码时,我感到非常惊讶。毕竟,只有一个字节可供使用。

我很少在代码中写入2,3,4或5的文字。我可以理解为什么-1,0和1可能会被特别对待,但我觉得设计师想要将4个宝贵的操作码放在恰好相当小的数字上似乎很神奇。

有谁知道这是否有充分理由?我低估了这些的好处吗?

2 个答案:

答案 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_0iconst_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 byte1byte1扩展为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所说,这些数字会比你想象的更频繁地使用