Tôi nghĩ rằng hầu hết các bạn đều biết đó goto
là một từ khóa dành riêng trong ngôn ngữ Java nhưng không thực sự được sử dụng. Và có lẽ bạn cũng biết đó goto
là một opcode Java Virtual Machine (JVM). Tôi nghĩ tất cả các cấu trúc kiểm soát dòng chảy phức tạp của Java, Scala và Kotlin được, ở mức JVM, thực hiện sử dụng một số sự kết hợp của goto
và ifeq
, ifle
, iflt
vv
Nhìn vào thông số JVM https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w tôi thấy cũng có một goto_w
mã opcode. Trong khi đó goto
có phần bù nhánh 2 byte, goto_w
lấy phần bù nhánh 4 byte. Thông số kỹ thuật nói rằng
Mặc dù lệnh goto_w có độ lệch nhánh 4 byte, các yếu tố khác giới hạn kích thước của phương thức là 65535 byte (§4.11). Giới hạn này có thể được nêu ra trong một bản phát hành tương lai của Máy ảo Java.
Nghe có vẻ như tôi goto_w
là bằng chứng trong tương lai, giống như một số các *_w
opcode khác . Nhưng nó cũng xảy ra với tôi rằng có lẽ có goto_w
thể được sử dụng với hai byte quan trọng hơn bằng 0 và hai byte ít quan trọng hơn giống như đối với goto
, với các điều chỉnh khi cần thiết.
Ví dụ, được đưa ra Trường hợp chuyển đổi Java này (hoặc 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.
chúng ta có thể viết lại như
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.
Tôi thực sự đã không thử điều này, vì có lẽ tôi đã mắc lỗi khi thay đổi "số dòng" để phù hợp với goto_w
s. Nhưng vì nó nằm trong thông số kỹ thuật, nên có thể làm được.
Câu hỏi của tôi là liệu có một lý do nào đó mà trình biên dịch hoặc trình tạo mã byte khác có thể sử dụng goto_w
với giới hạn 65535 hiện tại ngoài việc cho thấy rằng nó có thể được thực hiện không?
// ... repeat 10K times ...
Điều đó biên dịch? Tôi biết có giới hạn về kích thước của một lớp nguồn duy nhất ... nhưng tôi không biết chính xác nó là gì (tạo mã là lần duy nhất tôi thấy thứ gì đó thực sự đánh vào nó).