是否可以使用if和while将所有控制流图转换回来?

时间:2014-02-26 10:53:01

标签: if-statement while-loop jvm bytecode control-flow-graph

我想知道从单个方法(不允许递归)的典型control flow graphs(参见JVM bytecode)获得的所有how to是否可以转换回等效的if s和while代码。

如果没有,那么无法转换回ifwhile s的最小JVM字节码序列是什么?

2 个答案:

答案 0 :(得分:4)

如果没有极端的措施,字节码控制流可能无法转换回Java有几个原因。

  • JSR / RET - 这个指令对在Java中没有等价物。你能做的最好就是内联它。但是,如果它们是嵌套的,这将导致代码大小呈指数级增长。

  • 不可约循环 - 在Java中,每个循环都有一个入口点,它占据了循环的其余部分。 “不可简化”循环是具有多个不同入口点的循环,因此没有直接的Java等价物。有几种方法。我的首选解决方案是复制环体的一部分,尽管这也可能导致病理情况中的指数爆炸。另一种方法是将方法转换为while-switch状态机,但这会掩盖原始控制流。

示例指令序列是

ifnull L3
L2: nop
L3: goto L2

这是最简单的不可简化的循环。如果不改变结构或复制代码的一部分就不可能变成Java(尽管在这种情况下,没有实际的语句,所以复制也不会那么糟糕。)

  • 最后一部分是异常处理。 Java要求所有异常处理都是通过结构化的try / catch块完成的,而它的变体则是字节码。在字节码级别,异常处理程序基本上是另一种形式的goto。在病态情况下,你可以做的最好的事情是为每一个抛出并重复上述过程的指令创建一个单独的try catch。

答案 1 :(得分:2)

我认为跳转到循环中间在结构化代码中是不可表达的:

JMP L1 // jump into the middle of a loop
L2:
IFCMP L3 // loop condition
// do something inside the loop
L1:
// do something else inside the loop
JMP L2
L3:
// exit the loop

很抱歉,这不完全是JVM字节码,但你可以理解。