我正在使用ASM框架来操作一些java字节码。我只需要从switch指令中删除break语句。我的尝试从字节码中删除了goto指令,但不仅仅是这些与switch相关的指令(例如,所有来自类...)。
你怎么看?
答案 0 :(得分:0)
Java源代码中的BREAK语句与Java字节码中的任何内容之间没有明确的链接。一些带有BREAK语句的语言结构可能被编译为GOTO操作码,但我怀疑你能否在它们之间建立可靠的链接。
你唯一能做的就是在Java源代码中捕获BREAK语句的行号(假设那些行不会有任何其他语句)然后使用用行号信息编译的字节码你可以找到操作码对于那些线。
答案 1 :(得分:0)
goto
指令属于switch
语句,如果出现在两个切换字节码指令之一的上下文中。棘手的部分是决定它们是否代表break
。 lookupswitch
和tableswitch
都有一个分支目标列表,如果之前的指令这样的分支目标是goto
指令,它可能代表一个{ {1}}。这可以通过检查所有或至少大多数此类break
指令是否具有相同的目标来验证,该目标是goto
语句之后的下一条指令。如果您已在switch
语句后面确定了指令的字节码位置,则可以将该位置的所有switch
视为goto
。
但这种启发式方法可能会失败。请考虑以下代码:
break;
答案 2 :(得分:0)
通常,Java代码中的所有非异常,无条件分支都会编译为goto
(或goto_w
)。这包括break
语句,continue
语句,无条件循环和任意数量的控制流模式。您将无法在Java代码中的break
语句与goto
操作码之间进行任何简单映射。您可以通过进行一些控制流分析来确定哪些跳转就像一个开关break
,但它并不完美。
良好的学习经验可能是从Java反编译器中分离源代码,因为反编译器必须重构switch
语句并找出如何将跳转表示为break
,continue
Procyon和Krakatau都是开源的。我写了前者,但代码库很大而且令人生畏,所以它可能不是最好的选择。