If statement 是否可以使用if和while将所有控制流图翻译回?

If statement 是否可以使用if和while将所有控制流图翻译回?,if-statement,while-loop,jvm,bytecode,control-flow-graph,If Statement,While Loop,Jvm,Bytecode,Control Flow Graph,我想知道是否所有从单个方法(不允许递归)的典型(参见)中获得的数据都可以转换回等效的ifs和whiles代码 如果不是,最小的JVM字节码序列是什么,它不能被翻译回Ifs和whiles?我认为跳转到循环中间在结构化代码中是无法表达的: JMP L1 // jump into the middle of a loop L2: IFCMP L3 // loop condition // do something inside the loop L1: // do something else ins

我想知道是否所有从单个方法(不允许递归)的典型(参见)中获得的数据都可以转换回等效的
if
s和
while
s代码


如果不是,最小的JVM字节码序列是什么,它不能被翻译回
If
s和
while
s?

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

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字节码,但您可以理解。

字节码控制流在没有极端措施的情况下可能无法翻译回Java有几个原因

  • JSR/RET——这个指令对在Java中没有等价物。您所能做的最好的事情就是将其内联。然而,如果它们是嵌套的,这将导致代码大小的指数级增长

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

下面是一个示例指令序列

ifnull L3
L2: nop
L3: goto L2
这是最简单的不可约循环。如果不改变结构或复制部分代码(尽管在本例中,没有实际的语句,所以复制不会那么糟糕),就不可能转换成Java

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

这个问题似乎与SO无关,因为它与具体的实施问题无关。这个例子是错误的,因为你仍然只有一个入口点。但是基本思想是正确的。但是请注意,
jsr
ret
在Java 6中被弃用了。@raphw但是由于向后兼容,它们总是一个问题。是的,但是OP询问了典型的字节码。现在大多数库都是为Java 6或更高版本编译的。@raphw典型的字节码是直接从Java编译而来的,因此它总是可以转换回Java(不可否认,现实世界的反编译器有一些限制,所以足够复杂的Java仍然会把它们搞糟)实际上,DREAM反编译器框架中提出的方法将通过引入变量和添加条件来删除循环中的非结构化项。这是一种比代码复制或状态机好得多的方法,它们都是幼稚和通用的想法,与问题不匹配。与DREAM相关的论文包含了所有细节,它生成了goto free代码,没有代码重复。虽然他们专注于C语言,但这些思想适用于Java字节码