Is the creation of Java class files deterministic?
Let's put it this way:
I can easily produce an entirely conforming Java compiler that never produces the same .class
file twice, given the same .java
file.
I could do this by tweaking all kinds of bytecode construction or by simply adding superfluous attributes to my method (which is allowed).
Given that the specification does not require the compiler to produce byte-for-byte identical class files, I'd avoid depending such a result.
However, the few times that I've checked, compiling the same source file with the same compiler with the same switches (and the same libraries!) did result in the same .class
files.
Update: I've recently stumbled over this interesting blog post about the implementation of switch
on String
in Java 7. In this blog post, there are some relevant parts, that I'll quote here (emphasis mine):
In order to make the compiler's output predictable and repeatable, the maps and sets used in these data structures are
LinkedHashMap
s andLinkedHashSet
s rather than justHashMaps
andHashSets
. In terms of functional correctness of code generated during a given compile, usingHashMap
andHashSet
would be fine; the iteration order does not matter. However, we find it beneficial to havejavac
's output not vary based on implementation details of system classes .
This pretty clearly illustrates the issue: The compiler is not required to act in a deterministic manner, as long as it matches the spec. The compiler developers, however, realize that it's generally a good idea to try (provided it's not too expensive, probably).
There is no obligation for the compilers to produce the same bytecode on each platform. You should consult the different vendors' javac
utility to have a specific answer.
I will show a practical example for this with file ordering.
Let's say that we have 2 jar files: my1.jar
and My2.jar
. They're put in the lib
directory, side-by-side. The compiler reads them in alphabetical order (since this is lib
), but the order is my1.jar
, My2.jar
when the file system is case insensitive , and My2.jar
, my1.jar
if it is case sensitive.
The my1.jar
has a class A.class
with a method
public class A { public static void a(String s) {}}
The My2.jar
has the same A.class
, but with different method signature (accepts Object
):
public class A { public static void a(Object o) {}}
It is clear that if you have a call
String s = "x"; A.a(s);
it will compile a method call with different signature in different cases. So, depending on your filesystem case sensitiveness, you will get different class as a result.
Short Answer - NO
Long Answer
They bytecode
need not be the same for different platform. It's the JRE (Java Runtime Environment) which know how exactly to execute the bytecode.
If you go through the Java VM specification you'll come to know that this needs not to be true that the bytecode is same for different platforms.
Going through the class file format, it shows the structure of a class file as
ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count];}
Checking about the minor and major version
minor_version, major_version
The values of the minor_version andmajor_version items are the minor and major version numbers of thisclass file.Together, a major and a minor version number determine theversion of the class file format. If a class file has major versionnumber M and minor version number m, we denote the version of itsclass file format as M.m. Thus, class file format versions may beordered lexicographically, for example, 1.5 < 2.0 < 2.1. A Javavirtual machine implementation can support a class file format ofversion v if and only if v lies in some contiguous range Mi.0 vMj.m. Only Sun can specify what range of versions a Java virtualmachine implementation conforming to a certain release level of theJava platform may support.1
Reading more through the footnotes
1 The Java virtual machine implementation of Sun's JDK release 1.0.2supports class file format versions 45.0 through 45.3 inclusive. Sun'sJDK releases 1.1.X can support class file formats of versions in therange 45.0 through 45.65535 inclusive. Implementations of version 1.2of the Java 2 platform can support class file formats of versions inthe range 45.0 through 46.0 inclusive.
So, investigating all this shows that the class files generated on different platforms need not be identical.