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

Mik*_*yer 2 jvm if-statement bytecode while-loop control-flow-graph

我想知道从单个方法(不允许递归)的典型JVM 字节码(参见如何)获得的所有控制流图是否都可以转换回等效的s 和s 代码。ifwhile

如果不是,则无法转换回ifs 和whiles的最小 JVM 字节码序列是多少?

Ant*_*ony 5

如果不采取极端措施,字节码控制流可能无法转换回 Java 的原因有很多。

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

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

一个示例指令序列是

ifnull L3
L2: nop
L3: goto L2
Run Code Online (Sandbox Code Playgroud)

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

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