[英]Do different Java Compilers (where the vendor is different) produce different bytecode
Given the same major version, say Java 7, do different Java Compilers (eg, Oracle's hotspot, JRockit, or IBM's J9 etc...) compile a given java source code file into the same bytcode? 给定相同的主要版本,比如Java 7,做不同的Java编译器(例如,Oracle的热点,JRockit或IBM的J9等......)将给定的java源代码文件编译成相同的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. 扫描Java 7语言规范似乎正在讨论的是语言的语义,而不是将代码转换为字节码。
This question is not the same as do different major.minor versions for a given vendor produce the same bytecode. 这个问题与不同的major.minor版本不同,给定供应商生成相同的字节码。 That question is already answered here - with a could be .
这个问题已在这里得到解答 - 可能是 。
From the following answer to Is the creation of Java class files deterministic? 从以下答案到Java类文件的创建是否确定? 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 .
和这个问题的答案是指评论此沿侧两个答案上述问题MAJOR.MINOR 1和2 ,我收集了答案,我的问题是YES。
Excerpts for the above are: 上述摘录如下:
The JLS leaves many implementation details to vary from one implementation to another.
JLS留下了许多实现细节,从一个实现到另一个实现。
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.
但是,JLS没有指定从源代码到生成的字节代码的1:1映射,因此您不应该依赖于生成完全相同的字节代码。
Yet a comment here implies differently: 然而, 这里的评论意味着不同:
It's the compiler, ie javac, creating the code using a BLAH BLAH BLAH.
它是编译器,即javac,使用BLAH BLAH BLAH创建代码。 This has nothing to do with HotSpot.
这与HotSpot无关。
It implies that given a code X all javac implementations (same version/different vendors) must produce the same Y bytecode. 这意味着给定代码X所有javac实现(相同版本/不同供应商)必须生成相同的Y字节码。
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? 可以给出明确的答案吗?
There are 2 questions: 有两个问题:
The answer to 1 is yes, obviously. 显然,1的答案是肯定的。 For, otherwise, the JLS had to fully specify the bytecode to generate for each and every language construct.
否则,JLS必须完全指定为每个语言结构生成的字节码。 But it doesn't.
但事实并非如此。
The answer to 2 I don't know for sure, though I have heard that eclipse compiler generates slightly different code than javac in some cases. 2的答案我不确定,虽然我听说eclipse编译器在某些情况下产生的代码与javac略有不同。 Should be easy to verify.
应该很容易验证。
The comment in question does not actually disagree. 有问题的评论实际上并不反对。 Note that you are mixing up two different things here: Java bytecode compilers (
javac
) and Java just-in-time compilers (such as HotSpot or J9). 请注意,您在这里混合了两个不同的东西:Java字节码编译器(
javac
)和Java即时编译器(例如HotSpot或J9)。 You normally use some javac implementation to translate java source code to java bytecode. 您通常使用一些javac实现将java源代码转换为java字节码。
Then you take the bytecode and execute it in a JVM, which uses another compiler. 然后你获取字节码并在JVM中执行它,它使用另一个编译器。
Again, there are two sets of compilers: 同样,有两组编译器:
.java
to .class
) .java
到.class
) .class
files) .class
文件) ( EDIT: Neither of these are guaranteed to produce identical results (ie, the same java
file can yield different class
files, and the same class
file can yield different machine code when the JIT is done with it.)) ( 编辑:这些都不能保证产生相同的结果(即,相同的
java
文件可以产生不同的class
文件,并且当JIT完成时,相同的class
文件可以产生不同的机器代码。))
The reason for having two sequential compilation processes is that if you wrap everything into one compiler, you lose two properties: 有两个顺序编译过程的原因是,如果将所有内容都包装到一个编译器中,则会丢失两个属性:
There are differences between the compilers and interestingly some of the permitted differences led to problems in the past. 编译器之间存在差异,有趣的是,一些允许的差异导致了过去的问题。
Some differences are small, eg some compilers optimize x=x+1
to produce the same bytecode as x++
, others don't. 一些差异很小,例如,一些编译器优化
x=x+1
以产生与x++
相同的字节码,而其他编译器则不然。
Others can have more impact, eg 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. 但是用于计算默认
serialVersionUID
的算法在所有类成员上使用哈希码,甚至是合成成员。
As a consequence, compiling with javac
or the first Eclipse versions created classes with incompatible serialVersionUID
s. 因此,使用
javac
或第一个Eclipse版本进行编译会创建具有不兼容的serialVersionUID
的类。 Today, Eclipse uses the same name schema for synthetic members as javac
and issues a warning about missing explicit serialVersionUID
s in Serializable
classes by default. 今天,Eclipse对合成成员使用与
javac
相同的名称模式,并在默认情况下发出有关在Serializable
类中缺少显式serialVersionUID
的警告。
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. 仍然有很多自由,甚至包装
pack200
包可能会创建具有不同于原始类的字节代码的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.