Identical Java sources compile to binary differing classes
When you compare using beyond compare, comparision is done based on contents of the files. But in the build process just the timestamp of the source files are checked for change. So it your source file's lastmodified date changes it will be recompiled.
Different versions of Java can add different meta data which is often ignored by a decompiler.
I suggest you try using javap -c -v
for more of the details in a file. If this doesn't help you can use the ASMifierClassVisitor which looks at every byte.
Assuming that the JDK versions, build tool versions, and build / compilation options are identical, I can still think of a number of possible sources of differences:
Timestamps - class files may1 contain compilation timestamps. Unless you run the compilations at exactly the same times, different compilations of the same file would result 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.
Values of imported compile-time constants - when a class
A
uses a compile-time constant defined in another classB
(see JLS for the definition of a "compile time constant"), the value of the constant is incorporated intoA
s class file. So if you compileA
against different versions ofB
(with different values for the constants), the code ofA
is likely to be different.Differences due to
identityHashcode
being used inHashMap
keys by the compiler could lead to differences in map iteration order in some step. This could affect.class
file generation in a way that is not significant, but still shows up as a.class
file difference. For example, constant pool entries could end up in a different order.Differences in signatures of external classes / methods; e.g. if you changed a dependency version in one of your POM files.
Differences in the effective build classpaths might result in differences in the order in which imported classes are found. This might in turn 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:
- files appearing in different order in the directories of external JAR files,
- files being compiled in different order due to the source files being in different order when your build tool iterates them2, or
- parallelism in the build (if you have that enabled).
There is a possible workaround for the problem with file ordering: use the undocumented -XDsortfiles
option as described in JDK-7003006. (Kudos to @Holger for knowing about that.)
Note that you don't normally see the actual order of files in file system directories. Commandline tools like ls
and dir
, and file browsers will typically sort the entries (in name or timestamp order) before displaying them.
1 - This is compiler dependent. Also, it is not guaranteed that javap
will show the timestamps ... if they are present.
2 - The OS gives no guarantees that listing a directory (at the syscall level) will return the file system objects in a deterministic order ... or the same order, if you have removed and re-added files.
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.
Different JDK produce different binary classes (optimizations, but also class version number). There are compilation options, too (a JDK may compile in an older format, or it can add debug information).