是否有任何 Java 反编译器可以正确反编译对重载方法的调用?[关闭]
-
27-09-2019 - |
题
考虑这个(恕我直言简单)的例子:
public class DecompilerTest {
public static void main(String[] args) {
Object s1 = "The", s2 = "answer";
doPrint((Object) "You should know:");
for (int i = 0; i < 2; i++) {
doPrint(s1);
doPrint(s2);
s1 = "is";
s2 = new Integer(42);
}
System.out.println();
}
private static void doPrint(String s1) {
System.out.print("Wrong!");
}
private static void doPrint(Object s1) {
System.out.print(s1 + " ");
}
}
使用源/目标级别 1.1 进行编译,无需调试信息(即,不应存在局部变量信息)并尝试反编译它。我尝试了 Jad、JD-GUI 和 Fernflower,它们都至少有一个调用错误(即。e.该程序打印了“错误!”至少一次)
难道真的没有java反编译器可以推断出正确的强制转换,这样就不会调用错误的重载吗?
编辑: 目标级别 1.1,以便不存在任何特定于 Java6 的快速验证信息。这可能会给反编译器一个线索,表明 s1 已被声明为 Object
而不是作为 String
. 。即使没有这些信息,反编译器也应该能够反编译代码(不一定获得原始变量类型,但显示相同的行为),特别是因为许多混淆器也剥离了它。
反编译器出错的地方:
- 他们错过了演员阵容
(Object)
在第一次通话中。 - 他们推断出类型
s1
成为String
, ,但忘记在调用中添加强制转换doPrint
(以便调用 String 版本而不是 Object 版本)。 - 一个蹩脚的(我什至没有列出)甚至推断出类型
s2
为 String,导致代码无法编译。
无论如何,这段代码永远不会调用 String
重载,但反编译的代码却重载了。
解决方案
喀拉喀托岛 正确处理所有重载方法,甚至是在基本类型上重载的方法,这是大多数反编译器都会出错的。它总是将参数转换为被调用方法的确切类型,因此代码可能比必要的更混乱,但至少它是正确的。
披露:我是《喀拉喀托》的作者。
其他提示
你好,米希,
回复晚了非常抱歉。我正在复制我的答案 http://www.reversed-java.com/fernflower/forum?threadfolder=2_DE
你的问题实际上是一个众所周知的问题。让我们来看看:
1) 纯字节码不包含任何有关对象变量类型的信息,因此在第一遍中 s1 和 s2 被声明为 Object。
2) 反编译器正在努力为每个变量分配最好的可能类型(= Fernflower 中实现的“最窄类型原则”)。因此 s1 和 s2 被正确识别为 String 的实例。
3) 调用 doPrint 为我们提供了正确方法的直接链接
私有静态无效 doPrint(对象 s1)
4)到目前为止一切都还好,对吧?现在我们有一个字符串变量 s1 传递给一个函数,该函数需要一个对象。我们需要投射它吗?您可能会认为并非如此,因为 Object 是 String 的超类型。但我们确实这样做了 - 因为同一个类中还有另一个函数具有相同的名称和不同的参数签名。所以我们需要分析整个类来确定是否需要强制转换。
5) 一般来说,这意味着我们需要分析所有库中所有引用的类,包括java运行时。工作量巨大!事实上,此功能已在 Fernflower 的某些 alpha 版本中实现,但由于性能和内存损失,尚未在生产中实现。其他提到的反编译器在设计上就缺乏这种能力。
希望我已经澄清了一些事情:)
用于反编译的 JadClipse Eclipse 插件还提供了 JODE 反编译器,您可能想尝试一下。当贾德放弃时我会使用它。
Dava 反编译器还使用 Soot,我上次查看时,它在重建原始 Java 代码方面非常雄心勃勃。我没有尝试过你的例子,但你可能想看看。 http://www.sable.mcgill.ca/dava/
南河三族 应正确处理重载方法调用。与 Krakatau 一样,Procyon 最初会为与目标方法不完全匹配的每个方法参数插入强制转换。然而,其中大部分将在反编译的后期阶段被删除,该阶段会识别并消除冗余的强制转换。仅当 Procyon 可以验证这样做不会导致调用绑定到不同的方法时,它才会删除调用参数上的强制转换。例如,如果 .class
声明该方法无法解析,它根本不会尝试删除强制转换,因为它无法知道哪些重载可能会发生冲突。
补充一下之前的答案:以下是截至 2015 年 3 月的现代反编译器列表:
- 南河三族
- 病死率
- 京东
- 蕨花
它们都支持重载方法。
您可以在线测试上述反编译器,无需安装,并做出您自己的明智选择。云中的 Java 反编译器: http://www.javadecompilers.com/