Ich denke, die meisten von Ihnen wissen, dass dies goto
ein reserviertes Schlüsselwort in der Java-Sprache ist, aber nicht tatsächlich verwendet wird. Und Sie wissen wahrscheinlich auch, dass goto
es sich um einen JVM-Opcode (Java Virtual Machine) handelt. Ich rechne damit , alle hoch entwickelten Kontrollflussstrukturen von Java, Scala und Kotlin wird, auf der Ebene JVM, implementiert eine Kombination aus goto
und ifeq
, ifle
, iflt
usw.
Wenn ich mir die JVM-Spezifikation https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w ansehe, sehe ich, dass es auch einen goto_w
Opcode gibt. Während goto
ein 2-Byte-Verzweigungsversatz verwendet wird, goto_w
wird ein 4-Byte-Verzweigungsversatz verwendet. Die Spezifikation besagt das
Obwohl der Befehl goto_w einen 4-Byte-Verzweigungsversatz benötigt, begrenzen andere Faktoren die Größe einer Methode auf 65535 Byte (§4.11). Diese Grenze kann in einer zukünftigen Version der Java Virtual Machine angehoben werden.
Es klingt für mich goto_w
zukunftssicher, wie einige der anderen *_w
Opcodes. Mir fällt aber auch ein, dass goto_w
die beiden möglicherweise signifikanteren Bytes auf Null und die beiden weniger signifikanten Bytes goto
wie bei den erforderlichen Anpassungen verwendet werden könnten .
Beispiel: Java Switch-Case (oder 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.
wir könnten es umschreiben als
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.
Ich habe dies nicht wirklich versucht, da ich wahrscheinlich einen Fehler gemacht habe, die "Zeilennummern" zu ändern, um die goto_w
s aufzunehmen. Aber da es in der Spezifikation enthalten ist, sollte es möglich sein, dies zu tun.
Meine Frage ist, ob es einen Grund gibt, den ein Compiler oder ein anderer Bytecode-Generator goto_w
mit dem aktuellen Grenzwert von 65535 verwenden könnte, außer um zu zeigen, dass dies möglich ist.
// ... repeat 10K times ...
Das kompiliert? Ich weiß, dass die Größe einer einzelnen Quellklasse begrenzt ist ... aber ich weiß nicht genau, was es ist (Codegenerierung ist das einzige Mal, dass ich gesehen habe, dass etwas tatsächlich getroffen wurde).