简体   繁体   English

哪些设置会影响已编译的java .class文件的布局? 如何判断两个编译的类是否相等?

[英]What settings affect the layout of compiled java .class files? How can you tell if two compiled classes are equal?

I have an app that was compiled with the built-in Eclipse "Compile" task. 我有一个使用内置Eclipse“编译”任务编译的应用程序。 Then I decided to move the build procedure into Ant's javac , and the result ended being smaller files. 然后我决定将构建过程移动到Ant的javac ,结果变成了较小的文件。

Later I discovered that adjusting the debuglevel to "vars,lines,source" I could embed the same debug information that Eclipse did, and in a lot of cases files stayed exactly the same size but the internal layout was different. 后来我发现将调试级别调整为"vars,lines,source"我可以嵌入与Eclipse相同的调试信息,并且在很多情况下文件保持完全相同的大小但内部布局不同。 And as a consequence, I couldn't use md5sum signatures to determine if they were exactly the same version. 因此,我无法使用md5sum签名来确定它们是否完全相同。

Besides debug information, what can be the reason that 2 supposedly equal files get a different internal layout or size? 除了调试信息之外,2个所谓的相等文件获得不同内部布局或大小的原因是什么?

And how can you compare compiled .class files? 你怎么能比较编译的.class文件?

THere is no required order for things such as the order of the constant pool entries (essentially all of the symbol info) as well as the attributes for each field/method/class. 对于诸如常量池条目的顺序(基本上所有符号信息)以及每个字段/方法/类的属性之类的事物而言,这不是必需的顺序。 Different compilers are free to write out in whatever order they want. 不同的编译器可以按他们想要的顺序自由写出。

You can compared compiled classes, but you would need to dig into the class file structure and parse it. 您可以比较编译的类,但您需要深入研究类文件结构并解析它。 There are libraries out there for doing that, like BCEL or ASM , but I am not 100% sure they will help you with what you want to do. 有像这样的图书馆,比如BCELASM ,但我不是百分百肯定他们会帮助你做你想做的事情。

The ASM Eclipse plugin has a bytecode comparer in it. ASM Eclipse 插件中有一个字节码比较器。 You select two classes, right click, and do Compare With / Each Other Bytecode. 您选择两个类,右键单击,并与比较/相互字节码。

An important thing to note is that Eclipse does not use javac. 需要注意的一点是Eclipse不使用javac。 Eclipse has its own compiler, the JDT , and so differences in the resulting .class files do not surprise me. Eclipse有自己的编译器, JDT ,因此产生的.class文件的差异并不让我感到惊讶。 I'd expect them to not be verbatim, because they are different compilers. 我希望它们不是逐字的,因为它们是不同的编译器。

Due to their differences, there exists code that compiles with javac but not JDT, and vice versa. 由于它们的不同,存在使用javac而不是JDT编译的代码,反之亦然。 Typically I have seen the differences in the two become apparent in cases of heavy use of generics 通常我已经看到,在大量使用仿制药的情况下,两者的差异变得明显

Most importantly, the stack slots for local variables can be arranged arbitrarily without changing the semantics of the code. 最重要的是,局部变量的堆栈槽可以任意排列,而不会改变代码的语义。 So basically, you cannot compare compiled class files without parsing and normalizing them - quite a lot of effort. 所以基本上,你不能比较编译的类文件而不解析和规范它们 - 相当多的努力。

Why do you want to do that anyway? 你为什么要这样做呢?

as Michale B said, it can be arbitrary. 正如Michale B所说,它可以是任意的。

I work on systems that are using file sizes as security. 我在使用文件大小作为安全性的系统上工作。 If the .class files change in size, the class won't be given certain permissions. 如果.class文件的大小发生更改,则不会为该类授予特定权限。

Normally that would be easy to get around, but we have fairly complete control over the environment, so it's actually pretty functional. 通常这很容易解决,但我们对环境有相当完全的控制,所以它实际上非常实用。

Anyway, any time the classes that are watched are recompiled, it seems, we have to recalculate the size. 无论如何,只要重新编译被监视的类,我们就必须重新计算大小。

Another thing--a special key number is generated when the file is compiled. 另一件事 - 编译文件时会生成一个特殊的密钥号。 I don't know much about this, but it often prevents classes from working together. 我对此并不了解,但它经常阻止课程一起工作。 I believe the procedure is, compile class A and save it (call it a1). 我相信程序是,编译A类并保存它(称之为a1)。 compile class a again (a2). 再次编译类a(a2)。 Compile class b against class a2. 针对类a2编译类b。 Try to run b against a1. 尝试针对a1运行b。 I believe that in this case it will fail at runtime. 我相信在这种情况下它会在运行时失败。

If you could learn more about that key number, it might give you the info you are after. 如果您可以了解有关该密钥的更多信息,它可能会为您提供您所需的信息。

For the comparisson you can decompile your class files and play with the sources generated. 对于comparisson,您可以反编译您的类文件并使用生成的源进行播放。 See this . 看到这个

Eclipse是否正在使用一些工具来协助在调试器中运行?

Ultimately the configurations being used are probably making the difference. 最终,正在使用的配置可能正在发挥作用。 Assuming they are using the same versions of Java, there are a host of options that are available for the compile configuration (JDK compliance, class file compatibility and a host of debugging information options). 假设他们使用的是相同版本的Java,那么可以使用许多选项来进行编译配置(JDK合规性,类文件兼容性和一系列调试信息选项)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM