【问题标题】:Why does the JVM have the iconst_2 - iconst_5 opcodes?为什么 JVM 有 iconst_2 - iconst_5 操作码?
【发布时间】:2015-06-09 23:32:39
【问题描述】:

在阅读 JVM 规范时(就像一个人一样),当我遇到 7 个iconst_<i> 操作码时,我感到非常惊讶。毕竟,只有一个字节可以玩。

我很少在我的代码中编写 2、3、4 或 5 的字面量。我可以理解为什么 -1、0 和 1 可能会被特殊对待,但让我感到惊讶的是,设计者想要在恰好很小的数字上使用 4 个宝贵的操作码。

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

【问题讨论】:

  • 有 255 个操作码可用。在设计 VM 指令集时,很难在所有这些指令集附近使用它们。显然,吉姆·高斯林认为这是个好主意,而且在你用完之前都是免费的,就像赠送免费的剧院门票一样,为什么不呢?

标签: java jvm opcodes


【解决方案1】:

我认为,您的假设是正确的:只是为了使字节码更小,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,即使您在源代码中没有这样的常量。

【讨论】:

    【解决方案2】:

    希望这可以澄清您的问题为什么要浪费 4 Opcode ..

    查看此代码的字节码

    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。 Size 的差异是由于 bipush 有 2 个字节,一个字节操作码,第二个字节立即常量值

    bipush 格式:

    bipush
    byte
    

    您可以从5: bipush 6 的字节码行中看到,而iconst_<n> 仅使用 1 个字节。

    所以这样的字节码是为一些通常推送的数字定义的,以 提高字节码执行效率并减小 字节码流。

    正如塔吉尔所说,这些数字的使用频率会比你想象的要多

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-15
      • 1970-01-01
      • 2013-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      相关资源
      最近更新 更多