Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do different Java Compilers (where the vendor is different) produce different bytecode

Given the same major version, say Java 7, do different Java Compilers (e.g., Oracle's hotspot, JRockit, or IBM's J9 etc...) compile a given java source code file into the same bytcode?

Scanning the Java 7 language spec it would seem that what is being discussed is the semantics of the language and not the transformation of the code into bytecode.

This question is not the same as do different major.minor versions for a given vendor produce the same bytecode. That question is already answered here - with a could be.

From the following answer to Is the creation of Java class files deterministic? and a comment to that answer that refers to this along side two answers to the major.minor question above 1 and 2, I gather that the answer to my question is YES.

Excerpts for the above are:

The JLS leaves many implementation details to vary from one implementation to another.

and

However the JLS does not specify a 1:1 mapping from source code to the generated byte code, so you should not rely on the exact same byte code to be generated.

Yet a comment here implies differently:

It’s the compiler, i.e. javac, creating the code using a BLAH BLAH BLAH. This has nothing to do with HotSpot.

It implies that given a code X all javac implementations (same version/different vendors) must produce the same Y bytecode.

I cannot see how that is so, but I am unable to verify that it is not (or that what I think, see above) is correct.

Can a definitive answer be given?

like image 206
Yaneeve Avatar asked Nov 28 '13 12:11

Yaneeve


1 Answers

There are differences between the compilers and interestingly some of the permitted differences led to problems in the past.

Some differences are small, e.g. some compilers optimize x=x+1 to produce the same bytecode as x++, others don’t.

Others can have more impact, e.g. the standard did not specify how to generate the names of synthetic members used to implement inner class access to private members (and similar things) in the past (I don’t know whether it does today). But the algorithm for calculating a default serialVersionUID used a hash code over all class members, even synthetic ones.

As a consequence, compiling with javac or the first Eclipse versions created classes with incompatible serialVersionUIDs. Today, Eclipse uses the same name schema for synthetic members as javac and issues a warning about missing explicit serialVersionUIDs in Serializable classes by default.

There’s still a lot of freedom and even packing with pack200 and unpacking may create classes with different byte code than the original classes.

like image 89
Holger Avatar answered Sep 25 '22 23:09

Holger