我知道大多数人都知道这goto
是Java语言中的保留关键字,但实际上并未使用。您可能还知道这goto
是Java虚拟机(JVM)操作码。我认为所有的Java,Scala和科特林的复杂的控制流结构,在JVM的水平,使用的某种组合来实现goto
和ifeq
,ifle
,iflt
,等。
查看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
想到,也许可以将两个较高有效字节清零,并将两个较低有效字节与for相同goto
,并根据需要进行调整。
例如,给定以下Java Switch-Case(或Scala Match-Case):
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
s 可能犯了一个错误。但是由于它在规范中,所以应该可以做到。
我的问题是,goto_w
除了表明可以做到这一点之外,是否还有其他原因可以与当前65535限制一起使用编译器或其他字节码生成器?
// ... repeat 10K times ...
编译吗?我知道单个源类的大小是有限制的……但是我不知道它到底是什么(代码生成是我唯一见到过的东西)。