我试图通过反编译.class文件来了解Java编译器的工作原理。我使用过Java反编译器(http://jd.benow.ca/)和showmycode(http://www.showmycode.com/) 它们在.java文件中显示了不同的源代码。 为什么?我应该相信哪一个。
.java文件
class HelloWorld{
public static void main(String[] args){
System.out.println("Hello, World!");
}
}
.class文件,由java反编译器反编译:
import java.io.PrintStream;
class HelloWorld
{
public static void main(String[] paramArrayOfString)
{
System.out.println("Hello, World!");
}
}
.class文件,由showmycode解密
import java.io.PrintStream;
class HelloWorld {
HelloWorld() {
}
public static void main(string args[])
{
system.out.println("Hello, World!");
}
}
答案 0 :(得分:8)
反编译器无法重新创建原始源代码,它只能创建一个新的源代码,它将编译成与原始源代码相同的二进制文件。
(假设 showmycode 将解决他们的案例问题,请参见下文)三个源代码 - 原始代码,由 java反编译器创建的代码和由 showmycode 是幂等。它们以不同的方式编写,但做同样的事情。两个反编译都是对的。
以下是解释的差异:
[]
对数组的位置:声明String[] foo
和String foo[]
是相同的。我建议总是去String[] foo
,因为在Java中(而不是C),作为数组是类型的属性,而不是变量。{}
,缩进等:大多数情况下都没有关系。调试信息(堆栈跟踪的行数)可能有点重要,但这不是代码的重要行为的一部分,这是我们感兴趣的。请注意, showmycode 似乎与类型名称的情况有关。 Java区分大小写,它必须是System
和String
,而不是system
和string
。似乎 showmycode 会出错,这意味着除非您手动修复所有这些类型名称,否则无法再次编译代码。
showmycode 的另一个问题是它如何处理varargs方法。我将main的签名更改为public static void main(String... args)
以查看我得到的内容,并且我得到了public static transient void main(string args[])
,但是没有编译。现在反编译器需要生成正确的,可编译的源代码, showmycode 不会。
答案 1 :(得分:0)
因为有几种不同的方式来编写大多数语句,所有这些都归结为相同的目标代码。通常没有单一的正确反编译。