我正在玩Java字节码生成(使用Clojure和https://github.com/jgpc42/insn),目前我正在尝试为嵌套
for
循环生成字节码,下面是相关部分生成的字节码,但是当我尝试运行它时,我得到:
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 114
与
for
相关的部分字节码:
111: bipush 0
113: istore_0
114: iload_0
115: bipush 3
117: if_icmpge 154
120: bipush 0
122: istore_1
123: iload_0
124: bipush 3
126: if_icmpge 147
129: invokestatic #14 // Method my/pkg/RaspIvok.getInvoker:()Lrasp_lang/lib/core2/Invoker;
132: invokestatic #44 // Method my/pkg/RaspIvok.getPrintln:()Lmy/pkg/Test/Println;
135: ldc #46 // String Hello
137: invokevirtual #49 // Method rasp_lang/lib/core2/Invoker.call:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
140: pop
141: iinc 1, 1
144: goto 123
147: pop
148: iinc 0, 1
151: goto 114
154: return
如何理解以解决问题有任何帮助吗?
谢谢
在每条字节码指令中,类验证器都有一个关于堆栈有多大以及每个槽中有哪些类型的精确模型。
代码可以自然地(仅从顶部)或通过 151 处的
GOTO
“流入”114。
进入第 114 项的这两条路线没有相同的堆栈模型。要么是上面的类型不一样,要么是尺寸不一样。
快速浏览一下,在“注释”中说明堆栈上的效果:
我们进入空栈,然后:
+1 111: bipush 0
-1 113: istore_0
+1 114: iload_0
+1 115: bipush 3
-2 117: if_icmpge 154
+1 120: bipush 0
-1 122: istore_1
+1 123: iload_0
+1 124: bipush 3
-2 126: if_icmpge 147
+1 129: invokestatic #14 // Method my/pkg/RaspIvok.getInvoker:()Lrasp_lang/lib/core2/Invoker;
+1 132: invokestatic #44 // Method my/pkg/RaspIvok.getPrintln:()Lmy/pkg/Test/Println;
+1 135: ldc #46 // String Hello
-3+1 137: invokevirtual #49 // Method rasp_lang/lib/core2/Invoker.call:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-1 140: pop
0 141: iinc 1, 1
0 144: goto 123
-1 147: pop
0 148: iinc 0, 1
0 151: goto 114
0 154: return
一切都处于平衡状态。除了 147: pop 之外,它毫无意义,意味着当您到达“151: goto 114”时总和为 -1,但当您“自然”到达 114 时总和为 0。
我不知道147:流行音乐是从哪里来的。看起来,如果你摆脱它,这应该可行。