2011-09-28 80 views
2

考慮下面的Java代碼:爲什麼Eclipse Java編譯器檢查從null轉換?

public class Test { 
    public static void use(Object[] x) { 
    } 

    public static void main(String[] args) { 
     Object[] x = null; 

     use(x); 
    } 
} 

由Eclipse 3.7編譯器爲main()產生的Java字節碼看起來是這樣的:

public static void main(java.lang.String[]); 
    Code: 
    0: aconst_null 
    1: checkcast #20; //class "[Ljava/lang/Object;" 
    4: astore_1 
    5: aload_1 
    6: invokestatic #21; //Method use:([Ljava/lang/Object;)V 
    9: return 

相反,這是由OpenJDK的1.6生成的字節碼.0b22編譯器:

public static void main(java.lang.String[]); 
    Code: 
    0: aconst_null 
    1: astore_1 
    2: aload_1 
    3: invokestatic #2; //Method use:([Ljava/lang/Object;)V 
    6: return 

請注意,Eclipse編譯器會發出額外的checkcast操作碼。它似乎也只是爲數組而不是其他變量類型。

我的問題:

  1. 據我所知,null是分配給任何類,包括數組。是否任何感到checkcast已知null價值?

  2. 是否額外checkcast影響性能?

  3. 難道這被認爲是Eclipse Java編譯器中的一個錯誤嗎?

注:

我可以部分答案(2),至少只要在OpenJDK 1.6.0b22 JVM而言。我執行了一個簡單的基準測試,並在定時緊密循環中對null進行了幾項分配。這種或那種方式我無法檢測到任何一致的性能差異。

這就是說,我的基準是非常簡單,任何半體面的優化器將有可能使它無用的,所以它可能無法代表現實世界的應用程序。我希望JVM會總是優化了那個checkcast操作碼,但可能並非如此。

回答

2

關於你提到的第一個問題,你是對的,checkcast指令存在是多餘的。 根據Sun's Java Hotspot wiki空檢查和實例檢查是便宜的。

我打開了一個issue in Eclipse Bugzilla以獲得來自Eclipse編譯器團隊的反饋,但正如之前指出的那樣,這是多餘的,但無害的檢查。它隻影響字節碼的大小,Java HotSpot編譯器可能會在運行時應用類型檢查優化。

更新:from Eclipse compiler team它看起來像another old bug的副作用。

+0

+1的錯誤報告和一個有趣的閱讀... – thkala

2
  1. 不,檢查沒有意義,因爲null總是可以轉換爲任何引用類型。但它不會傷害任何東西。
  2. 任何體面的JIT無論如何都會優化檢查(它實際上是無操作),所以最大的成本是指令佔用的三個字節。
  3. 我不認爲這是一個「錯誤」,因爲生成的字節碼按預期工作 - 它永遠不會觸發ClassCastException,作爲值總是已知的和正確的 - 而且,你顯然也看到了,有沒有真正的性能差異無論哪種方式。這是一個改進的機會,但無論如何會打破
+0

+1的完整答案 – thkala

相關問題