如何仅使用ASM从交换机中删除break语句?

时间:2014-03-22 13:16:13

标签: java java-bytecode-asm bytecode-manipulation

我正在使用ASM框架来操作一些java字节码。我只需要从switch指令中删除break语句。我的尝试从字节码中删除了goto指令,但不仅仅是这些与switch相关的指令(例如,所有来自类...)。

你怎么看?

3 个答案:

答案 0 :(得分:0)

Java源代码中的BREAK语句与Java字节码中的任何内容之间没有明确的链接。一些带有BREAK语句的语言结构可能被编译为GOTO操作码,但我怀疑你能否在它们之间建立可靠的链接。

你唯一能做的就是在Java源代码中捕获BREAK语句的行号(假设那些行不会有任何其他语句)然后使用用行号信息编译的字节码你可以找到操作码对于那些线。

答案 1 :(得分:0)

goto指令属于switch语句,如果出现在两个切换字节码指令之一的上下文中。棘手的部分是决定它们是否代表breaklookupswitchtableswitch都有一个分支目标列表,如果之前的指令这样的分支目标是goto指令,它可能代表一个{ {1}}。这可以通过检查所有或至少大多数此类break指令是否具有相同的目标来验证,该目标是goto语句之后的下一条指令。如果您已在switch语句后面确定了指令的字节码位置,则可以将该位置的所有switch视为goto

但这种启发式方法可能会失败。请考虑以下代码:

break;

答案 2 :(得分:0)

通常,Java代码中的所有非异常,无条件分支都会编译为goto(或goto_w)。这包括break语句,continue语句,无条件循环和任意数量的控制流模式。您将无法在Java代码中的break语句与goto操作码之间进行任何简单映射。您可以通过进行一些控制流分析来确定哪些跳转就像一个开关break,但它并不完美。

良好的学习经验可能是从Java反编译器中分离源代码,因为反编译器必须重构switch语句并找出如何将跳转表示为breakcontinue Procyon和Krakatau都是开源的。我写了前者,但代码库很大而且令人生畏,所以它可能不是最好的选择。