簡體   English   中英

不同的Java編譯器(供應商不同)會產生不同的字節碼

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

給定相同的主要版本,比如Java 7,做不同的Java編譯器(例如,Oracle的熱點,JRockit或IBM的J9等......)將給定的java源代碼文件編譯成相同的bytcode?

掃描Java 7語言規范似乎正在討論的是語言的語義,而不是將代碼轉換為字節碼。

這個問題與不同的major.minor版本不同,給定供應商生成相同的字節碼。 這個問題已在這里得到解答 - 可能是

從以下答案Java類文件的創建是否確定? 和這個問題的答案是指評論沿側兩個答案上述問題MAJOR.MINOR 12 ,我收集了答案,我的問題是YES。

上述摘錄如下:

JLS留下了許多實現細節,從一個實現到另一個實現。

但是,JLS沒有指定從源代碼到生成的字節代碼的1:1映射,因此您不應該依賴於生成完全相同的字節代碼。

然而, 這里的評論意味着不同:

它是編譯器,即javac,使用BLAH BLAH BLAH創建代碼。 這與HotSpot無關。

這意味着給定代碼X所有javac實現(相同版本/不同供應商)必須生成相同的Y字節碼。

我不明白這是怎么回事,但我無法證實它不是(或者我認為,見上文)是正確的。

可以給出明確的答案嗎?

有兩個問題:

  1. 不同的java編譯器是否可以為相同的源代碼生成不同的字節碼?
  2. 它們實際上是否為同一源生成不同的字節碼。

顯然,1的答案是肯定的。 否則,JLS必須完全指定為每個語言結構生成的字節碼。 但事實並非如此。

2的答案我不確定,雖然我聽說eclipse編譯器在某些情況下產生的代碼與javac略有不同。 應該很容易驗證。

有問題的評論實際上並不反對。 請注意,您在這里混合了兩個不同的東西:Java字節碼編譯器( javac )和Java即時編譯器(例如HotSpot或J9)。 您通常使用一些javac實現將java源代碼轉換為java字節碼。

然后你獲取字節碼並在JVM中執行它,它使用另一個編譯器。

同樣,有兩組編譯器:

  1. 字節碼編譯器( .java.class
  2. 即時編譯器作為Java虛擬機的一部分(執行.class文件)

編輯:這些都不能保證產生相同的結果(即,相同的java文件可以產生不同的class文件,並且當JIT完成時,相同的class文件可以產生不同的機器代碼。))

有兩個順序編譯過程的原因是,如果將所有內容都包裝到一個編譯器中,則會丟失兩個屬性:

  1. 您編譯的程序將是特定於平台的
  2. 您的程序將不會(輕松地)執行Java提供的一些優化和高級語言功能(反射,動態類加載)。

編譯器之間存在差異,有趣的是,一些允許的差異導致了過去的問題。

一些差異很小,例如,一些編譯器優化x=x+1以產生與x++相同的字節碼,而其他編譯器則不然。

其他人可能會產生更大的影響,例如標准沒有指定如何生成過去用於實現私有成員(和類似事物)的內部類訪問的合成成員的名稱(我不知道它是否在今天)。 但是用於計算默認serialVersionUID的算法在所有類成員上使用哈希碼,甚至是合成成員。

因此,使用javac或第一個Eclipse版本進行編譯會創建具有不兼容的serialVersionUID的類。 今天,Eclipse對合成成員使用與javac相同的名稱模式,並在默認情況下發出有關在Serializable類中缺少顯式serialVersionUID的警告。

仍然有很多自由,甚至包裝pack200包可能會創建具有不同於原始類的字節代碼的類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM