Reputation: 14543
Currently we are in the process of re-scripting all of our build system for a large project (around 2000 source files) and there has been talk of doing a binary comparison on the files to ensure that everything is correct which leads to the following question: Is the output of javac
guaranteed to be same across compilations or could it be subject to change?
Another question implied that the constant pool could have a different order, but assuming we are able to control for the order of the files going into the javac
call is there still a potential for differences? We are using Ant and Maven as part of the build if that may influence things as well.
Upvotes: 6
Views: 589
Reputation: 47729
The only way to assure equivalence is to get one of the several class file parsers, parse the files, then do the heavy work of figuring out differences due to constant pool order changes, etc. The main problem is that reordering the constant pool will change numeric values that reference the constants, some of which are in table elements, some of which are in bytecodes. Doable, but definitely non-trivial, and probably not practical unless you already have most of the framework in place for some other reason (such as bytecode modification).
Upvotes: 1
Reputation: 183321
The bytecode is absolutely not guaranteed to be the same; for one thing, compilers are allowed to perform optimizations that don't affect any guaranteed behaviors. The Java Language Specification even mentions, in a few places, optimizations that a compiler might perform; for example, of the string concatenation operator +
, it notes that:
An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate
String
object. To increase the performance of repeated string concatenation, a Java compiler may use theStringBuffer
class or a similar technique to reduce the number of intermediateString
objects that are created by evaluation of an expression.
[link]
Upvotes: 5
Reputation: 3128
I am not an expert on the compiler, but I tend to believe the other answers saying that binary comparison is not 100% reliable.
I'd consider another alternative: You should be able to inspect the artifacts your build system creates (.jars & .wars, etc.) and ensure that each have the expected contents, and even that the size of each file is within a fairly tight tolerance.
If your build script is generating source and compiling it, then you should be able to do comparisons against the generated source, which I expect would be 100% stable from build to build. (Or at least predictable).
Hope this helps!
Upvotes: 0