JVM的任何编译器都使用“宽” goto吗?

问题描述 投票:3回答:2

我想你们大多数人都知道goto是Java语言中的保留关键字,但实际上并未使用。您可能还知道goto是Java虚拟机(JVM)操作码。我认为在JVM级别上,Java,Scala和Kotlin的所有复杂控制流结构都是使用gotoifeqifleiflt等的某种组合实现的。>

查看JVM规范https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w,我发现还有一个goto_w操作码。 goto占用2字节的分支偏移,而goto_w占用4字节的分支偏移。规范指出

尽管goto_w

指令采用4字节的分支偏移量,但其他因素将方法的大小限制为65535字节(第4.11节)。 Java虚拟机的未来版本中可能会提高此限制。

在我看来,goto_w与其他*_w操作码一样,都是面向未来的。但我也想到,也许可以使用goto_w将两个较高有效字节清零,而将两个较低有效字节与goto相同,并根据需要进行调整。]

例如,鉴于此Java切换案例(或Scala匹配案例):

     12: lookupswitch  {
                112785: 48 // case "red"
               3027034: 76 // case "green"
              98619139: 62 // case "blue"
               default: 87
          }
      48: aload_2
      49: ldc           #17                 // String red
      51: invokevirtual #18
            // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      54: ifeq          87
      57: iconst_0
      58: istore_3
      59: goto          87
      62: aload_2
      63: ldc           #19                 // String green
      65: invokevirtual #18
            // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      68: ifeq          87
      71: iconst_1
      72: istore_3
      73: goto          87
      76: aload_2
      77: ldc           #20                 // String blue
      79: invokevirtual #18 
      // etc.

我们可以将其重写为

     12: lookupswitch  { 
                112785: 48
               3027034: 78
              98619139: 64
               default: 91
          }
      48: aload_2
      49: ldc           #17                 // String red
      51: invokevirtual #18
            // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      54: ifeq          91 // 00 5B
      57: iconst_0
      58: istore_3
      59: goto_w        91 // 00 00 00 5B
      64: aload_2
      65: ldc           #19                 // String green
      67: invokevirtual #18
            // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      70: ifeq          91
      73: iconst_1
      74: istore_3
      75: goto_w          91
      79: aload_2
      81: ldc           #20                 // String blue
      83: invokevirtual #18 
      // etc.

我实际上没有尝试过,因为更改“行号”以适应goto_w可能犯了一个错误。但是由于它在规范中,所以应该可以这样做。

我的问题是,是否有原因导致编译器或其他字节码生成器使用goto_w和当前的65535限制,而不是表明可以这样做?

我想你们大多数人都知道goto是Java语言中的保留关键字,但实际上并未使用。您可能还知道goto是Java虚拟机(JVM)操作码。我认为所有的...

java jvm goto
2个回答
1
投票

方法代码的大小可以最大为65K。

[short goto的分支偏移是一个有符号的16位整数:从-32768到32767。


0
投票

当分支适合goto_w时,没有理由使用goto。但是您似乎错过了分支是relative

© www.soinside.com 2019 - 2024. All rights reserved.