4

我有一个使用内置 Eclipse“编译”任务编译的应用程序。然后我决定将构建过程移到 Ant 中javac,结果文件变小了。

后来我发现将调试级别调整为"vars,lines,source"可以嵌入与 Eclipse 相同的调试信息,并且在很多情况下,文件的大小完全相同,但内部布局不同。因此,我无法使用 md5sum 签名来确定它们是否完全相同。

除了调试信息之外,两个据称相等的文件获得不同的内部布局或大小的原因可能是什么?

以及如何比较已编译的 .class 文件?

4

8 回答 8

3

诸如常量池条目的顺序(基本上是所有符号信息)以及每个字段/方法/类的属性之类的东西没有必需的顺序。不同的编译器可以按照他们想要的任何顺序自由地写出来。

您可以比较已编译的类,但您需要深入研究类文件结构并对其进行解析。有一些图书馆可以做到这一点,比如BCELASM,但我不能 100% 确定它们会帮助你完成你想做的事情。

于 2009-03-13T20:41:54.423 回答
2

ASM Eclipse插件中有一个字节码比较器。您选择两个类,单击鼠标右键,然后进行比较/彼此字节码。

于 2009-03-13T22:02:20.610 回答
2

需要注意的重要一点是 Eclipse 不使用 javac。Eclipse 有自己的编译器JDT,因此生成的 .class 文件中的差异并不让我感到惊讶。我希望它们不是逐字记录,因为它们是不同的编译器。

由于它们的差异,存在使用 javac 而不是 JDT 编译的代码,反之亦然。通常,在大量使用泛型的情况下,我已经看到两者的差异变得明显

于 2009-03-13T22:19:43.783 回答
1

最重要的是,在不改变代码语义的情况下,局部变量的栈槽可以任意排列。所以基本上,如果不解析和规范化它们,你就无法比较编译的类文件 - 相当多的努力。

你为什么要这样做呢?

于 2009-03-13T20:08:47.407 回答
1

正如 Michale B 所说,它可以是任意的。

我在使用文件大小作为安全性的系统上工作。如果 .class 文件的大小发生变化,则不会授予该类某些权限。

通常这很容易解决,但我们可以完全控制环境,所以它实际上非常实用。

无论如何,每当重新编译所监视的类时,我们似乎都必须重新计算大小。

另一件事——编译文件时会生成一个特殊的密钥编号。我对此了解不多,但它经常阻止类一起工作。我相信程序是,编译A类并保存它(称之为a1)。再次编译 a 类(a2)。针对类 a2 编译类 b。尝试对 a1 运行 b。我相信在这种情况下它会在运行时失败。

如果您可以了解有关该密钥号码的更多信息,它可能会为您提供所需的信息。

于 2009-03-13T20:45:59.377 回答
1

对于比较,您可以反编译您的类文件并使用生成的源代码。看到这个

于 2009-03-13T20:56:43.717 回答
0

Eclipse 是否在做一些检测来帮助在调试器中运行?

于 2009-03-13T20:10:12.503 回答
0

最终,所使用的配置可能会有所不同。假设他们使用相同版本的 Java,则有许多选项可用于编译配置(JDK 合规性、类文件兼容性和大量调试信息选项)。

于 2009-03-13T20:12:00.987 回答