Java字节码生成嵌套循环:分支目标114栈映射帧不一致求助
嵌套for循环字节码生成栈映射帧不一致问题的解决
问题现象
使用Clojure结合insn库生成Java字节码时,嵌套for循环的代码运行抛出以下错误:
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 114
对应的字节码片段:
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
问题分析
错误根源是标签147处的pop指令完全多余:
- 当内层循环通过
if_icmpge跳转到147时,操作栈是空的,此时执行pop会导致栈下溢,同时破坏了栈映射帧的一致性。 - 验证器检查分支目标114时,发现两条路径(从113的
istore_0跳转、从151的goto跳转)的栈帧状态不匹配:前者栈为空,后者因为147的pop导致栈状态异常,最终触发VerifyError。
解决方案
移除字节码中标签147位置的pop指令,修改后的字节码片段如下:
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: iinc 0, 1 151: goto 114 154: return
修改后,内层循环结束跳转至147时,栈状态为空,直接执行iinc 0,1递增外层循环变量,再跳转至114进行条件判断。此时两条到达114的路径栈帧状态完全一致,验证器不会再抛出错误。
内容的提问来源于stack exchange,提问作者Édipo Féderle
相关产品推荐
相关产品推荐

