You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:40:28