相同的Java源代码编译成二进制不同的类 [英] Identical Java sources compile to binary differing classes

查看:319
本文介绍了相同的Java源代码编译成二进制不同的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以解释为什么相同的Java源码可以编译成不同的类文件。

Can anyone explain how identical Java sources can end up compiling to binary differing class files?

问题出现在以下情况:

The question arises from the following situation:

我们有一个相当大的应用程序(800+类),已经分支,重组,然后重新集成回主干。在重新整合之前,我们将干线合并到分支中,这是标准过程。

We have a fairly large application (800+ classes) which has been branched, restructured then reintegrated back into the trunk. Prior to reintegration, we merged the trunk into the branch, which is standard procedure.

最终结果是一组目录,其中包含分支源和一组目录以及中继源。使用Beyond比较,我们能够确定两组源是相同的。但是,在编译(相同的JDK 使用maven托管在IntelliJ v11),我们注意到大约十几个类文件是不同的。

The end result was a set of directories with the branch sources and a set of directories with the trunk sources. Using Beyond Compare we were able to determine that both sets of sources were identical. However, on compiling (same JDK using maven hosted in IntelliJ v11) we noticed that about a dozen or so of the class files were different.

当我们为每对显然不同的类文件反编译源代码时,我们最终使用相同的java源代码,所以就最终结果而言,物质。但为什么只有几个文件是不同的?

When we decompiled the source for each pair of apparently different class files we ended up with the same java source, so in terms of the end result, it doesn't seem to matter. But why is it that just a few of the files are different?

谢谢。

其他想法:

如果maven / javac以不同的顺序编译文件,可能会影响最终结果?

If maven/javac compiles files in a different sequence, might that affect the end result?

推荐答案

假设JDK和编译选项是相同的,我可以想到5个差异:

Assuming that the JDKs and compilation options are identical, I can think of 5 possible sources of differences:


  1. 时间戳 - 每个类文件都包含编译时间戳。除非您在完全相同的时间运行编译,否则同一文件的不同编译将有不同的时间戳。

  1. Timestamps - every class file contains compilation timestamps. Unless you run the compilations at exactly the same times, different compilations of the same file will have different timestamps.

源文件名路径 - 每个类文件包括路径名的源文件。如果使用不同的路径名编译两个树,类文件将包含不同的源路径名。

Source filename paths - each class file includes the pathname of the source file. If you compile two trees with different pathnames the class files will contain different source pathnames.

导入的编译时常量的值 - c> A 使用在另一个类 B 中定义的编译时常数(有关编译时常量的定义,请参阅JLS)常数的值被合并到 A 的类文件中。因此,如果您为不同版本的 B (具有不同的常量值)编译 A ,代码<$

Values of imported compile-time constants - when a class A uses a compile-time constant defined in another class B (see JLS for the definition of a "compile time constant"), the value of the constant is incorporated into As class file. So if you compile A against different versions of B (with different values for the constants), the code of A is likely to be different.

外部类/方法的签名差异;

Differences in signatures of external classes / methods; e.g. if you changed a dependency version in one of your POM files.

构建类路径中的差异可能导致导入类的顺序不同,可能会导致类文件的常量池中条目顺序的非显着差异。这可能是由于以下原因:

Differences in the build classpaths might result in differences in the order in which imported classes are found which might result in non-significant differences in the order of entries in the class file's Constant Pool. This could happen due to things such as:


  • 文件以不同顺序出现在外部JAR文件的目录中,

  • 由于在构建工具迭代它们时源文件的顺序不同,或者

  • 构建中的并行性(如果已启用), 。

请注意,通常不会看到文件的实际顺序FS目录,因为 ls dir 等工具默认在显示之前对条目进行排序。

Note that you don't normally see the actual order of files in FS directories, because tools like ls and dir default to sorting the entries before displaying them.

我应该补充的是,识别差异的原因的第一步是准确地确定它们是什么。你可能需要(需要)来做这个硬的方式 - 通过手动解码一对类文件,以确定他们实际上差异的地方...和差异实际意味着什么。

I should add that the first step to identifying the cause of the differences is to work out exactly what they are. You probably need (needed) to do that the hard way - by manually decoding a pair of class files to identify the places where they actually differences ... and what the differences actually mean.

这篇关于相同的Java源代码编译成二进制不同的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆