2011-09-28 49 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

相关问题