2013-10-02 26 views
4

是否有代碼優化由同一版本做過任何區別: 甲骨文Java編譯器 Apache的Java編譯器 IBM Java編譯器 OpenJDK的Java編譯器。 如果有什麼代碼會演示不同的優化?還是他們使用相同的編譯器?如果沒有已知的優化差異,那麼我可以在哪裏找到關於如何測試編譯器以進行不同優化的資源?是否有編譯器的區別 - Java的

+3

順便說一句 - 我所知,主要是優化實際上是由JIT編譯器@EelLee JIT編譯器是Java中的唯一真正的編譯器完成的,而不是編譯器本身 –

+0

。我不知道從源代碼到字節碼的轉換稱爲「編譯」的任何其他語言。 –

+0

@MarkoTopolnik似乎被廣泛使用。我不知道爲什麼你認爲「編譯」只適用於最終結果是本機代碼的情況。 – Kayaman

回答

3

相同版本的代碼優化是否存在差異:Oracle Java編譯器Apache Java編譯器IBM Java編譯器OpenJDK Java編譯器。

儘管編譯器可能非常不同,javac幾乎沒有優化。主要優化是恆定內聯,這是在JLS中指定的,因此是標準的(除了任何錯誤)

如果有什麼代碼會證明不同的優化?

你可以這樣做。

final String w = "world"; 
String a = "hello " + w; 
String b = "hello world"; 
String c = w; 
String d = "hello " + c; 
System.out.prinlnt(a == b); // these are the same String 
System.out.prinlnt(c == b); // these are NOT the same String 

在第一種情況下,常量被內聯並且在編譯時串聯字符串。在第二種情況下,連接在運行時執行並創建一個新的字符串。

還是他們使用相同的編譯器?

不,但99%的優化是在運行時由JIT執行的,因此這些對於給定版本的JVM是相同的。

如果沒有已知的優化差異,那麼我可以在哪裏找到關於如何測試用於不同優化的編譯器的資源?

我會很驚訝,如果有一個,因爲這聽起來不太有用。問題是JIT優化了預先構建的字節代碼模板,如果您嘗試優化字節代碼,您最終可能會混淆JIT並導致代碼較慢。即沒有考慮將運行的JVM就無法評估優化。

+0

以VIP班級字符串+1爲例:) –

3

不,他們不使用相同的編譯器。我無法對優化和東西發表太多評論,但下面是編譯器在工作中的不同之處。

public class Test { 
    public static void main(String[] args) { 
     int x = 1L; // <- this cannot compile 
    } 
} 

如果您使用標準的java編譯器,它會引發編譯錯誤,並且不會創建類文件。

但是,如果你使用的Eclipse Java編譯器ECJ,它不僅會拋出同樣的編譯錯誤,但也將創建一個類文件(YES,對於不可編譯的代碼,這使得歐洲法院一類文件,我不會說錯,但有點棘手),看起來像這樣。

public static void main(String[] paramArrayOfString) 
{ 
    throw new Error("Unresolved compilation problem: \n\tType mismatch: cannot convert from long to int.\n"); 
} 

話雖如此,這只是介於2個編譯器之間。其他編譯器可能有自己的工作方式。

P.S:我把這個例子從here

+0

這是一個有效的觀察,但也許值得一提的是,ECJ並不是一個「正確的」編譯器,因爲它故意違反了一些規則。在這個例子中(就像你說的那樣),類不能編譯,而ECJ無論如何都會生成字節碼。在給定相同輸入的情況下產生不同形式的合法/正確輸出的編譯器之間比較有趣的比較。但是,這很難舉例說明。 –

+0

@AndrzejDoyle - 我在大多數情況下都同意你的看法,但我真的不想把ECJ稱爲「不正確的編譯器」,因爲它故意違反了一些規則。這是我的看法,但每個人都有他們的觀點,我尊重你的觀點! – SudoRahul

0

我花費大量時間編寫的唯一編譯器是javac(正如其他人指出的那樣,在急切優化方面做得很少)和Eclipse編譯器。在編寫Java反編譯器時,我觀察到Eclipse編譯代碼的一些(通常令人沮喪的)差異,但並不是很多。其中一些可以被認爲是優化。其中:

  1. Eclipse編譯器似乎執行至少一些重複的代碼分析。如果兩個(或更多?)代碼塊分支到分離但等同的代碼塊,則等效目標塊可以平鋪爲具有多個條目跳轉的單個塊。我從來沒有見過javac執行這種類型的優化;等效塊總是會被放出。我記得所有的例子都發生在switch聲明中。此優化減少了方法大小(因此減小了文件大小),這可以提高負載和驗證時間。它甚至可能會導致解釋模式中的性能提高(特別是如果解釋器執行內聯操作時),但我想這樣的改進會很輕微。我懷疑這種方法一旦被JIT編譯就會有所作爲。它也使反編譯更加困難(grrr)。

  2. 基本塊通常以與javac完全不同的順序發射。這可能只是編譯器內部設計的一個副作用,也可能是編譯器試圖優化代碼佈局以減少跳轉次數。這是我通常留給JIT的那種優化,而且這種理念似乎對javac工作正常。

相關問題